{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Execute this cell to install dependencies\n",
    "%pip install sf-hamilton[visualization]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data Loaders Overview [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/dagworks-inc/hamilton/blob/main/examples/data_loaders/data_loaders.ipynb) [![GitHub badge](https://img.shields.io/badge/github-view_source-2b3137?logo=github)](https://github.com/apache/hamilton/blob/main/examples/data_loaders/data_loaders.ipynb)\n",
    "\n",
    "\n",
    "This example demonstrates how to build scalable and maintainable Extract-Transform-Load (ETL) pipelines using Hamilton, focusing on the Extract phase. Hamilton allows for easy switching between different data sources without the need for cluttered if-else statements, making the dataflow modular and easier to maintain.\n",
    "\n",
    "The goal is to show:\n",
    "1. How to load data from various sources.\n",
    "2. How to switch between different data sources using polymorphism.\n",
    "\n",
    "Three data loaders are used in this example:\n",
    "\n",
    "- Mock Data Loader: Generates mock data on the fly, useful for unit testing or quick iterations.\n",
    "- CSV Data Loader: Reads data from CSV files, useful for ad-hoc research.\n",
    "- DuckDB Data Loader: Loads data from a DuckDB database, representing more production-ready data pipelines.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pre-requisites"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You need to have the following installed and set up:\n",
    "- Hamilton\n",
    "- pandas\n",
    "- duckdb\n",
    "\n",
    "Execute the code commented below to install the above if you don't have them already installed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %pip install sf-hamilton[visualization] pandas duckdb==0.5.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Importing all the things you need\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/stefankrawczyk/.pyenv/versions/knowledge_retrieval-py39/lib/python3.9/site-packages/pyspark/pandas/__init__.py:50: UserWarning: 'PYARROW_IGNORE_TIMEZONE' environment variable was not set. It is required to set this environment variable to '1' in both driver and executor sides if you use pyarrow>=2.0.0. pandas-on-Spark will set it for you but it does not work if there is a Spark context already launched.\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "from hamilton import base\n",
    "import hamilton.driver\n",
    "%load_ext hamilton.plugins.jupyter_magic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating the data loaders modules"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `load_data_duckdb` module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"411pt\" height=\"293pt\"\n",
       " viewBox=\"0.00 0.00 411.05 292.80\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 288.8)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-288.8 407.05,-288.8 407.05,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-146.8 8,-276.8 92.85,-276.8 92.85,-146.8 8,-146.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.43\" y=\"-259.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-227.6C391.05,-227.6 325.2,-227.6 325.2,-227.6 319.2,-227.6 313.2,-221.6 313.2,-215.6 313.2,-215.6 313.2,-176 313.2,-176 313.2,-170 319.2,-164 325.2,-164 325.2,-164 391.05,-164 391.05,-164 397.05,-164 403.05,-170 403.05,-176 403.05,-176 403.05,-215.6 403.05,-215.6 403.05,-221.6 397.05,-227.6 391.05,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"332.25\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- connection -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>connection</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M272.2,-145.6C272.2,-145.6 141.1,-145.6 141.1,-145.6 135.1,-145.6 129.1,-139.6 129.1,-133.6 129.1,-133.6 129.1,-94 129.1,-94 129.1,-88 135.1,-82 141.1,-82 141.1,-82 272.2,-82 272.2,-82 278.2,-82 284.2,-88 284.2,-94 284.2,-94 284.2,-133.6 284.2,-133.6 284.2,-139.6 278.2,-145.6 272.2,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"170.65\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">connection</text>\n",
       "<text text-anchor=\"start\" x=\"139.9\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DuckDBPyConnection</text>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;signups -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>connection&#45;&gt;signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M266.3,-145.97C278.44,-152.63 291.17,-159.62 303.14,-166.18\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"301.2,-169.11 311.65,-170.85 304.57,-162.97 301.2,-169.11\"/>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-145.6C391.05,-145.6 325.2,-145.6 325.2,-145.6 319.2,-145.6 313.2,-139.6 313.2,-133.6 313.2,-133.6 313.2,-94 313.2,-94 313.2,-88 319.2,-82 325.2,-82 325.2,-82 391.05,-82 391.05,-82 397.05,-82 403.05,-88 403.05,-94 403.05,-94 403.05,-133.6 403.05,-133.6 403.05,-139.6 397.05,-145.6 391.05,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"339.38\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;churn -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>connection&#45;&gt;churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M284.58,-113.8C290.35,-113.8 296.11,-113.8 301.72,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"301.44,-117.3 311.44,-113.8 301.44,-110.3 301.44,-117.3\"/>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-63.6C391.05,-63.6 325.2,-63.6 325.2,-63.6 319.2,-63.6 313.2,-57.6 313.2,-51.6 313.2,-51.6 313.2,-12 313.2,-12 313.2,-6 319.2,0 325.2,0 325.2,0 391.05,0 391.05,0 397.05,0 403.05,-6 403.05,-12 403.05,-12 403.05,-51.6 403.05,-51.6 403.05,-57.6 397.05,-63.6 391.05,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"338.25\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;spend -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>connection&#45;&gt;spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M266.3,-81.63C278.44,-74.97 291.17,-67.98 303.14,-61.42\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"304.57,-64.63 311.65,-56.75 301.2,-58.49 304.57,-64.63\"/>\n",
       "</g>\n",
       "<!-- _connection_inputs -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>_connection_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"100.1,-136.1 0.75,-136.1 0.75,-91.5 100.1,-91.5 100.1,-136.1\"/>\n",
       "<text text-anchor=\"start\" x=\"15.55\" y=\"-108\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">db_path</text>\n",
       "<text text-anchor=\"start\" x=\"70.3\" y=\"-108\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _connection_inputs&#45;&gt;connection -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>_connection_inputs&#45;&gt;connection</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M100.22,-113.8C105.76,-113.8 111.53,-113.8 117.38,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"117.19,-117.3 127.19,-113.8 117.19,-110.3 117.19,-117.3\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"77.43,-191.1 23.43,-191.1 23.43,-154.5 77.43,-154.5 77.43,-191.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.43\" y=\"-167\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-246.1C72.85,-246.1 28,-246.1 28,-246.1 22,-246.1 16,-240.1 16,-234.1 16,-234.1 16,-221.5 16,-221.5 16,-215.5 22,-209.5 28,-209.5 28,-209.5 72.85,-209.5 72.85,-209.5 78.85,-209.5 84.85,-215.5 84.85,-221.5 84.85,-221.5 84.85,-234.1 84.85,-234.1 84.85,-240.1 78.85,-246.1 72.85,-246.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.43\" y=\"-222\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e0f8c40>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module load_data_duckdb --display\n",
    "# Loading duckdb data\n",
    "import duckdb\n",
    "import pandas as pd\n",
    "\n",
    "def connection(db_path: str) -> duckdb.DuckDBPyConnection:\n",
    "    return duckdb.connect(database=db_path)\n",
    "\n",
    "\n",
    "def spend(connection: duckdb.DuckDBPyConnection) -> pd.DataFrame:\n",
    "    return connection.execute(\"select * from marketing_spend\").fetchdf()\n",
    "\n",
    "\n",
    "def churn(connection: duckdb.DuckDBPyConnection) -> pd.DataFrame:\n",
    "    return connection.execute(\"select * from churn\").fetchdf()\n",
    "\n",
    "\n",
    "def signups(connection: duckdb.DuckDBPyConnection) -> pd.DataFrame:\n",
    "    return connection.execute(\"select * from signups\").fetchdf()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `load_data_csv` module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"510pt\" height=\"458pt\"\n",
       " viewBox=\"0.00 0.00 509.55 457.73\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 453.73)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-453.73 505.55,-453.73 505.55,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"31.75,-307.73 31.75,-441.73 139.85,-441.73 139.85,-307.73 31.75,-307.73\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-424.43\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-75.52C489.55,-75.52 423.7,-75.52 423.7,-75.52 417.7,-75.52 411.7,-69.52 411.7,-63.52 411.7,-63.52 411.7,-23.92 411.7,-23.92 411.7,-17.92 417.7,-11.93 423.7,-11.93 423.7,-11.93 489.55,-11.93 489.55,-11.93 495.55,-11.93 501.55,-17.93 501.55,-23.93 501.55,-23.93 501.55,-63.53 501.55,-63.53 501.55,-69.52 495.55,-75.52 489.55,-75.52\"/>\n",
       "<text text-anchor=\"start\" x=\"430.75\" y=\"-52.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-24.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn.load_data.data -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>churn.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M164.48,-184.5C164.48,-188.89 129.21,-192.45 85.8,-192.45 42.39,-192.45 7.13,-188.89 7.13,-184.5 7.13,-184.5 7.13,-112.95 7.13,-112.95 7.13,-108.56 42.39,-105 85.8,-105 129.21,-105 164.48,-108.56 164.48,-112.95 164.48,-112.95 164.48,-184.5 164.48,-184.5\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M164.48,-184.5C164.48,-180.11 129.21,-176.55 85.8,-176.55 42.39,-176.55 7.13,-180.11 7.13,-184.5\"/>\n",
       "<text text-anchor=\"start\" x=\"17.93\" y=\"-157.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.93\" y=\"-129.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- churn.select_data.data -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>churn.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M363.58,-180.52C363.58,-180.52 219.73,-180.52 219.73,-180.52 213.73,-180.52 207.73,-174.52 207.73,-168.52 207.73,-168.52 207.73,-128.93 207.73,-128.93 207.73,-122.92 213.73,-116.92 219.73,-116.92 219.73,-116.92 363.58,-116.92 363.58,-116.92 369.58,-116.92 375.58,-122.92 375.58,-128.93 375.58,-128.93 375.58,-168.52 375.58,-168.52 375.58,-174.52 369.58,-180.52 363.58,-180.52\"/>\n",
       "<text text-anchor=\"start\" x=\"218.53\" y=\"-157.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.53\" y=\"-129.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn.load_data.data&#45;&gt;churn.select_data.data -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>churn.load_data.data&#45;&gt;churn.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M164.74,-148.72C174.97,-148.72 185.55,-148.72 196.03,-148.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"195.82,-152.23 205.82,-148.73 195.82,-145.23 195.82,-152.23\"/>\n",
       "</g>\n",
       "<!-- signups.select_data.data -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>signups.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M370.7,-75.52C370.7,-75.52 212.6,-75.52 212.6,-75.52 206.6,-75.52 200.6,-69.52 200.6,-63.52 200.6,-63.52 200.6,-23.92 200.6,-23.92 200.6,-17.92 206.6,-11.93 212.6,-11.93 212.6,-11.93 370.7,-11.93 370.7,-11.93 376.7,-11.93 382.7,-17.93 382.7,-23.93 382.7,-23.93 382.7,-63.53 382.7,-63.53 382.7,-69.52 376.7,-75.52 370.7,-75.52\"/>\n",
       "<text text-anchor=\"start\" x=\"211.4\" y=\"-52.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.53\" y=\"-24.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- signups.select_data.data&#45;&gt;signups -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>signups.select_data.data&#45;&gt;signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M383.19,-43.72C389.02,-43.72 394.79,-43.72 400.37,-43.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"400.02,-47.23 410.02,-43.73 400.02,-40.23 400.02,-47.23\"/>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-180.52C489.55,-180.52 423.7,-180.52 423.7,-180.52 417.7,-180.52 411.7,-174.52 411.7,-168.52 411.7,-168.52 411.7,-128.93 411.7,-128.93 411.7,-122.92 417.7,-116.92 423.7,-116.92 423.7,-116.92 489.55,-116.92 489.55,-116.92 495.55,-116.92 501.55,-122.92 501.55,-128.93 501.55,-128.93 501.55,-168.52 501.55,-168.52 501.55,-174.52 495.55,-180.52 489.55,-180.52\"/>\n",
       "<text text-anchor=\"start\" x=\"437.88\" y=\"-157.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-129.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-285.52C489.55,-285.52 423.7,-285.52 423.7,-285.52 417.7,-285.52 411.7,-279.52 411.7,-273.52 411.7,-273.52 411.7,-233.93 411.7,-233.93 411.7,-227.93 417.7,-221.93 423.7,-221.93 423.7,-221.93 489.55,-221.93 489.55,-221.93 495.55,-221.93 501.55,-227.93 501.55,-233.93 501.55,-233.93 501.55,-273.52 501.55,-273.52 501.55,-279.52 495.55,-285.52 489.55,-285.52\"/>\n",
       "<text text-anchor=\"start\" x=\"436.75\" y=\"-262.43\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-234.43\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend.select_data.data -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>spend.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M364.7,-285.52C364.7,-285.52 218.6,-285.52 218.6,-285.52 212.6,-285.52 206.6,-279.52 206.6,-273.52 206.6,-273.52 206.6,-233.93 206.6,-233.93 206.6,-227.93 212.6,-221.93 218.6,-221.93 218.6,-221.93 364.7,-221.93 364.7,-221.93 370.7,-221.93 376.7,-227.93 376.7,-233.93 376.7,-233.93 376.7,-273.52 376.7,-273.52 376.7,-279.52 370.7,-285.52 364.7,-285.52\"/>\n",
       "<text text-anchor=\"start\" x=\"217.4\" y=\"-262.43\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.53\" y=\"-234.43\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend.select_data.data&#45;&gt;spend -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>spend.select_data.data&#45;&gt;spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M377,-253.72C384.85,-253.72 392.67,-253.72 400.15,-253.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"400.09,-257.23 410.09,-253.73 400.09,-250.23 400.09,-257.23\"/>\n",
       "</g>\n",
       "<!-- churn.select_data.data&#45;&gt;churn -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>churn.select_data.data&#45;&gt;churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M376.05,-148.72C384.16,-148.72 392.25,-148.72 399.99,-148.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"399.91,-152.23 409.91,-148.73 399.91,-145.23 399.91,-152.23\"/>\n",
       "</g>\n",
       "<!-- signups.load_data.data -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>signups.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M171.6,-79.5C171.6,-83.89 133.14,-87.45 85.8,-87.45 38.46,-87.45 0,-83.89 0,-79.5 0,-79.5 0,-7.95 0,-7.95 0,-3.56 38.46,0 85.8,0 133.14,0 171.6,-3.56 171.6,-7.95 171.6,-7.95 171.6,-79.5 171.6,-79.5\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M171.6,-79.5C171.6,-75.11 133.14,-71.55 85.8,-71.55 38.46,-71.55 0,-75.11 0,-79.5\"/>\n",
       "<text text-anchor=\"start\" x=\"10.8\" y=\"-52.42\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.93\" y=\"-24.42\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- signups.load_data.data&#45;&gt;signups.select_data.data -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>signups.load_data.data&#45;&gt;signups.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M172.07,-43.72C177.58,-43.72 183.15,-43.72 188.72,-43.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"188.63,-47.23 198.63,-43.73 188.63,-40.23 188.63,-47.23\"/>\n",
       "</g>\n",
       "<!-- spend.load_data.data -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>spend.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M165.6,-289.5C165.6,-293.89 129.83,-297.45 85.8,-297.45 41.77,-297.45 6,-293.89 6,-289.5 6,-289.5 6,-217.95 6,-217.95 6,-213.56 41.77,-210 85.8,-210 129.83,-210 165.6,-213.56 165.6,-217.95 165.6,-217.95 165.6,-289.5 165.6,-289.5\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M165.6,-289.5C165.6,-285.11 129.83,-281.55 85.8,-281.55 41.77,-281.55 6,-285.11 6,-289.5\"/>\n",
       "<text text-anchor=\"start\" x=\"16.8\" y=\"-262.43\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.93\" y=\"-234.43\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- spend.load_data.data&#45;&gt;spend.select_data.data -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>spend.load_data.data&#45;&gt;spend.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M165.91,-253.72C175.4,-253.72 185.17,-253.72 194.86,-253.72\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"194.68,-257.23 204.68,-253.73 194.68,-250.23 194.68,-257.23\"/>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M108.23,-352.03C108.23,-352.03 63.38,-352.03 63.38,-352.03 57.38,-352.03 51.38,-346.03 51.38,-340.03 51.38,-340.03 51.38,-327.43 51.38,-327.43 51.38,-321.43 57.38,-315.43 63.38,-315.43 63.38,-315.43 108.23,-315.43 108.23,-315.43 114.22,-315.43 120.23,-321.43 120.23,-327.43 120.23,-327.43 120.23,-340.03 120.23,-340.03 120.23,-346.03 114.23,-352.03 108.23,-352.03\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-327.93\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- materializer -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>materializer</title>\n",
       "<path fill=\"#ffffff\" stroke=\"black\" d=\"M131.85,-407.26C131.85,-409.29 111.21,-410.94 85.8,-410.94 60.39,-410.94 39.75,-409.29 39.75,-407.26 39.75,-407.26 39.75,-374.19 39.75,-374.19 39.75,-372.16 60.39,-370.51 85.8,-370.51 111.21,-370.51 131.85,-372.16 131.85,-374.19 131.85,-374.19 131.85,-407.26 131.85,-407.26\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M131.85,-407.26C131.85,-405.23 111.21,-403.59 85.8,-403.59 60.39,-403.59 39.75,-405.23 39.75,-407.26\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-384.93\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">materializer</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e1903d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module load_data_csv --display\n",
    "# Loading csv data\n",
    "import pandas as pd\n",
    "from hamilton.function_modifiers import load_from, value\n",
    "\n",
    "\n",
    "@load_from.csv(path=value(\"test_data/marketing_spend.csv\"))\n",
    "def spend(data: pd.DataFrame) -> pd.DataFrame:\n",
    "    \"\"\"Takes in the dataframe and then generates a date index column to it,\n",
    "    where each row is a day starting from 2020-01-01\"\"\"\n",
    "    data[\"date\"] = pd.date_range(start=\"2020-01-01\", periods=len(data), freq=\"D\")\n",
    "    return data\n",
    "\n",
    "\n",
    "@load_from.csv(path=value(\"test_data/churn.csv\"))\n",
    "def churn(data: pd.DataFrame) -> pd.DataFrame:\n",
    "    \"\"\"Takes in the dataframe and then generates a date index column to it,\n",
    "    where each row is a day starting from 2020-01-01\n",
    "    \"\"\"\n",
    "    data[\"date\"] = pd.date_range(start=\"2020-01-01\", periods=len(data), freq=\"D\")\n",
    "    return data\n",
    "\n",
    "\n",
    "@load_from.csv(path=value(\"test_data/signups.csv\"))\n",
    "def signups(data: pd.DataFrame) -> pd.DataFrame:\n",
    "    \"\"\"Takes in the dataframe and then generates a date index column to it,\n",
    "    where each row is a day starting from 2020-01-01\n",
    "    \"\"\"\n",
    "    data[\"date\"] = pd.date_range(start=\"2020-01-01\", periods=len(data), freq=\"D\")\n",
    "    return data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `load_data_mock` module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"109pt\" height=\"329pt\"\n",
       " viewBox=\"0.00 0.00 108.85 328.80\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 324.8)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-324.8 104.85,-324.8 104.85,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-237.8 8,-312.8 92.85,-312.8 92.85,-237.8 8,-237.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-295.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-63.6C83.35,-63.6 17.5,-63.6 17.5,-63.6 11.5,-63.6 5.5,-57.6 5.5,-51.6 5.5,-51.6 5.5,-12 5.5,-12 5.5,-6 11.5,0 17.5,0 17.5,0 83.35,0 83.35,0 89.35,0 95.35,-6 95.35,-12 95.35,-12 95.35,-51.6 95.35,-51.6 95.35,-57.6 89.35,-63.6 83.35,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"24.55\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-145.6C83.35,-145.6 17.5,-145.6 17.5,-145.6 11.5,-145.6 5.5,-139.6 5.5,-133.6 5.5,-133.6 5.5,-94 5.5,-94 5.5,-88 11.5,-82 17.5,-82 17.5,-82 83.35,-82 83.35,-82 89.35,-82 95.35,-88 95.35,-94 95.35,-94 95.35,-133.6 95.35,-133.6 95.35,-139.6 89.35,-145.6 83.35,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"30.55\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-227.6C83.35,-227.6 17.5,-227.6 17.5,-227.6 11.5,-227.6 5.5,-221.6 5.5,-215.6 5.5,-215.6 5.5,-176 5.5,-176 5.5,-170 11.5,-164 17.5,-164 17.5,-164 83.35,-164 83.35,-164 89.35,-164 95.35,-170 95.35,-176 95.35,-176 95.35,-215.6 95.35,-215.6 95.35,-221.6 89.35,-227.6 83.35,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"31.67\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-282.1C72.85,-282.1 28,-282.1 28,-282.1 22,-282.1 16,-276.1 16,-270.1 16,-270.1 16,-257.5 16,-257.5 16,-251.5 22,-245.5 28,-245.5 28,-245.5 72.85,-245.5 72.85,-245.5 78.85,-245.5 84.85,-251.5 84.85,-257.5 84.85,-257.5 84.85,-270.1 84.85,-270.1 84.85,-276.1 78.85,-282.1 72.85,-282.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-258\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e1a7610>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module load_data_mock --display\n",
    "# loading mock data\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "def spend() -> pd.DataFrame:\n",
    "    data = np.array(\n",
    "        [\n",
    "            (\n",
    "                \"2022-08-03T00:00:00.000000000\",\n",
    "                104052.98074001,\n",
    "                115300.21226012,\n",
    "                69384.46649019,\n",
    "                49474.45580366,\n",
    "                12851.6540992,\n",
    "                1498.5114764,\n",
    "                \"2022-08-03T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-04T00:00:00.000000000\",\n",
    "                103234.15793884,\n",
    "                115326.0151612,\n",
    "                71113.31018247,\n",
    "                52513.19734904,\n",
    "                12344.42778548,\n",
    "                1033.79398268,\n",
    "                \"2022-08-04T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-05T00:00:00.000000000\",\n",
    "                101816.40188563,\n",
    "                115194.04661767,\n",
    "                71367.20874633,\n",
    "                51795.51413309,\n",
    "                11536.41253561,\n",
    "                2101.46146166,\n",
    "                \"2022-08-05T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-06T00:00:00.000000000\",\n",
    "                102263.53043232,\n",
    "                115601.2888751,\n",
    "                71474.76280964,\n",
    "                52861.22158421,\n",
    "                11652.28867968,\n",
    "                1046.83170946,\n",
    "                \"2022-08-06T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-07T00:00:00.000000000\",\n",
    "                103271.09660695,\n",
    "                115306.96341012,\n",
    "                71888.99025677,\n",
    "                50742.70043588,\n",
    "                11160.23631976,\n",
    "                2521.31311947,\n",
    "                \"2022-08-07T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-08T00:00:00.000000000\",\n",
    "                100775.86701231,\n",
    "                116634.88666304,\n",
    "                71603.50462531,\n",
    "                52361.08798097,\n",
    "                12869.33161266,\n",
    "                3269.57027156,\n",
    "                \"2022-08-08T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-09T00:00:00.000000000\",\n",
    "                101527.74726883,\n",
    "                114868.8422755,\n",
    "                70260.81680881,\n",
    "                49647.9754876,\n",
    "                13187.07115589,\n",
    "                2134.71274923,\n",
    "                \"2022-08-09T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-10T00:00:00.000000000\",\n",
    "                101150.73295175,\n",
    "                114941.32547639,\n",
    "                68802.02668922,\n",
    "                49590.55466274,\n",
    "                13129.31334755,\n",
    "                3328.0293293,\n",
    "                \"2022-08-10T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-11T00:00:00.000000000\",\n",
    "                100317.64365959,\n",
    "                115682.20050942,\n",
    "                67735.95105252,\n",
    "                50621.23723767,\n",
    "                14019.11780391,\n",
    "                2360.4382216,\n",
    "                \"2022-08-11T00:00:00.000000000\",\n",
    "            ),\n",
    "            (\n",
    "                \"2022-08-12T00:00:00.000000000\",\n",
    "                102024.067597,\n",
    "                116770.81592363,\n",
    "                66244.22984364,\n",
    "                49503.73825509,\n",
    "                14533.2726457,\n",
    "                1868.18205207,\n",
    "                \"2022-08-12T00:00:00.000000000\",\n",
    "            ),\n",
    "        ],\n",
    "        dtype=[\n",
    "            (\"index\", \"<M8[ns]\"),\n",
    "            (\"facebook\", \"<f8\"),\n",
    "            (\"twitter\", \"<f8\"),\n",
    "            (\"tv\", \"<f8\"),\n",
    "            (\"youtube\", \"<f8\"),\n",
    "            (\"radio\", \"<f8\"),\n",
    "            (\"billboards\", \"<f8\"),\n",
    "            (\"date\", \"<M8[ns]\"),\n",
    "        ],\n",
    "    )\n",
    "    return pd.DataFrame.from_records(data)\n",
    "\n",
    "\n",
    "def churn() -> pd.DataFrame:\n",
    "    data = np.array(\n",
    "        [\n",
    "            (\"2022-08-03T00:00:00.000000000\", 160, 53, \"2022-08-03T00:00:00.000000000\"),\n",
    "            (\"2022-08-04T00:00:00.000000000\", 162, 54, \"2022-08-04T00:00:00.000000000\"),\n",
    "            (\"2022-08-05T00:00:00.000000000\", 162, 50, \"2022-08-05T00:00:00.000000000\"),\n",
    "            (\"2022-08-06T00:00:00.000000000\", 161, 53, \"2022-08-06T00:00:00.000000000\"),\n",
    "            (\"2022-08-07T00:00:00.000000000\", 160, 49, \"2022-08-07T00:00:00.000000000\"),\n",
    "            (\"2022-08-08T00:00:00.000000000\", 160, 52, \"2022-08-08T00:00:00.000000000\"),\n",
    "            (\"2022-08-09T00:00:00.000000000\", 161, 53, \"2022-08-09T00:00:00.000000000\"),\n",
    "            (\"2022-08-10T00:00:00.000000000\", 160, 57, \"2022-08-10T00:00:00.000000000\"),\n",
    "            (\"2022-08-11T00:00:00.000000000\", 156, 56, \"2022-08-11T00:00:00.000000000\"),\n",
    "            (\"2022-08-12T00:00:00.000000000\", 148, 58, \"2022-08-12T00:00:00.000000000\"),\n",
    "        ],\n",
    "        dtype=[(\"index\", \"<M8[ns]\"), (\"womens\", \"<i8\"), (\"mens\", \"<i8\"), (\"date\", \"<M8[ns]\")],\n",
    "    )\n",
    "    return pd.DataFrame.from_records(data)\n",
    "\n",
    "\n",
    "def signups() -> pd.DataFrame:\n",
    "    data = np.array(\n",
    "        [\n",
    "            (\"2022-08-03T00:00:00.000000000\", 2184, 429, \"2022-08-03T00:00:00.000000000\"),\n",
    "            (\"2022-08-04T00:00:00.000000000\", 2164, 461, \"2022-08-04T00:00:00.000000000\"),\n",
    "            (\"2022-08-05T00:00:00.000000000\", 2159, 454, \"2022-08-05T00:00:00.000000000\"),\n",
    "            (\"2022-08-06T00:00:00.000000000\", 2157, 449, \"2022-08-06T00:00:00.000000000\"),\n",
    "            (\"2022-08-07T00:00:00.000000000\", 2121, 478, \"2022-08-07T00:00:00.000000000\"),\n",
    "            (\"2022-08-08T00:00:00.000000000\", 2151, 517, \"2022-08-08T00:00:00.000000000\"),\n",
    "            (\"2022-08-09T00:00:00.000000000\", 2133, 541, \"2022-08-09T00:00:00.000000000\"),\n",
    "            (\"2022-08-10T00:00:00.000000000\", 2160, 565, \"2022-08-10T00:00:00.000000000\"),\n",
    "            (\"2022-08-11T00:00:00.000000000\", 2135, 609, \"2022-08-11T00:00:00.000000000\"),\n",
    "            (\"2022-08-12T00:00:00.000000000\", 2116, 633, \"2022-08-12T00:00:00.000000000\"),\n",
    "        ],\n",
    "        dtype=[(\"index\", \"<M8[ns]\"), (\"womens\", \"<i8\"), (\"mens\", \"<i8\"), (\"date\", \"<M8[ns]\")],\n",
    "    )\n",
    "    return pd.DataFrame.from_records(data)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `prep_data` module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"841pt\" height=\"810pt\"\n",
       " viewBox=\"0.00 0.00 840.75 809.60\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 805.6)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-805.6 836.75,-805.6 836.75,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"32.38,-454.8 32.38,-584.8 117.22,-584.8 117.22,-454.8 32.38,-454.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"74.8\" y=\"-567.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- youtube_spend -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>youtube_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M421.05,-637.6C421.05,-637.6 323.7,-637.6 323.7,-637.6 317.7,-637.6 311.7,-631.6 311.7,-625.6 311.7,-625.6 311.7,-586 311.7,-586 311.7,-580 317.7,-574 323.7,-574 323.7,-574 421.05,-574 421.05,-574 427.05,-574 433.05,-580 433.05,-586 433.05,-586 433.05,-625.6 433.05,-625.6 433.05,-631.6 427.05,-637.6 421.05,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"322.5\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_marketing_spend -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>total_marketing_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M645.65,-637.6C645.65,-637.6 499.55,-637.6 499.55,-637.6 493.55,-637.6 487.55,-631.6 487.55,-625.6 487.55,-625.6 487.55,-586 487.55,-586 487.55,-580 493.55,-574 499.55,-574 499.55,-574 645.65,-574 645.65,-574 651.65,-574 657.65,-580 657.65,-586 657.65,-586 657.65,-625.6 657.65,-625.6 657.65,-631.6 651.65,-637.6 645.65,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"498.35\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_marketing_spend</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- youtube_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>youtube_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M433.39,-605.8C446.92,-605.8 461.6,-605.8 476.19,-605.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"475.78,-609.3 485.78,-605.8 475.78,-602.3 475.78,-609.3\"/>\n",
       "</g>\n",
       "<!-- total_signups -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>total_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M615.27,-227.6C615.27,-227.6 529.93,-227.6 529.93,-227.6 523.93,-227.6 517.93,-221.6 517.93,-215.6 517.93,-215.6 517.93,-176 517.93,-176 517.93,-170 523.93,-164 529.93,-164 529.93,-164 615.27,-164 615.27,-164 621.27,-164 627.27,-170 627.27,-176 627.27,-176 627.27,-215.6 627.27,-215.6 627.27,-221.6 621.27,-227.6 615.27,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"528.73\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_signups</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- acquisition_cost -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>acquisition_cost</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M820.75,-452.6C820.75,-452.6 716.65,-452.6 716.65,-452.6 710.65,-452.6 704.65,-446.6 704.65,-440.6 704.65,-440.6 704.65,-401 704.65,-401 704.65,-395 710.65,-389 716.65,-389 716.65,-389 820.75,-389 820.75,-389 826.75,-389 832.75,-395 832.75,-401 832.75,-401 832.75,-440.6 832.75,-440.6 832.75,-446.6 826.75,-452.6 820.75,-452.6\"/>\n",
       "<text text-anchor=\"start\" x=\"715.45\" y=\"-429.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">acquisition_cost</text>\n",
       "<text text-anchor=\"start\" x=\"749.58\" y=\"-401.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_signups&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>total_signups&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M627.56,-209.27C644.45,-215.51 662.17,-224.38 675.65,-236.8 717.28,-275.15 742.64,-336.53 755.93,-377.73\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"752.52,-378.56 758.83,-387.08 759.2,-376.49 752.52,-378.56\"/>\n",
       "</g>\n",
       "<!-- total_customers -->\n",
       "<g id=\"node16\" class=\"node\">\n",
       "<title>total_customers</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M820,-186.6C820,-186.6 717.4,-186.6 717.4,-186.6 711.4,-186.6 705.4,-180.6 705.4,-174.6 705.4,-174.6 705.4,-135 705.4,-135 705.4,-129 711.4,-123 717.4,-123 717.4,-123 820,-123 820,-123 826,-123 832,-129 832,-135 832,-135 832,-174.6 832,-174.6 832,-180.6 826,-186.6 820,-186.6\"/>\n",
       "<text text-anchor=\"start\" x=\"716.2\" y=\"-163.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_customers</text>\n",
       "<text text-anchor=\"start\" x=\"749.58\" y=\"-135.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_signups&#45;&gt;total_customers -->\n",
       "<g id=\"edge24\" class=\"edge\">\n",
       "<title>total_signups&#45;&gt;total_customers</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M627.67,-184.38C648.2,-180.04 671.96,-175.02 694,-170.37\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"694.46,-173.85 703.52,-168.36 693.02,-167 694.46,-173.85\"/>\n",
       "</g>\n",
       "<!-- womens_signups -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>womens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M428.55,-309.6C428.55,-309.6 316.2,-309.6 316.2,-309.6 310.2,-309.6 304.2,-303.6 304.2,-297.6 304.2,-297.6 304.2,-258 304.2,-258 304.2,-252 310.2,-246 316.2,-246 316.2,-246 428.55,-246 428.55,-246 434.55,-246 440.55,-252 440.55,-258 440.55,-258 440.55,-297.6 440.55,-297.6 440.55,-303.6 434.55,-309.6 428.55,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"315\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>womens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M440.82,-248.84C450.45,-244.76 460.24,-240.65 469.55,-236.8 481.68,-231.78 494.65,-226.5 507.14,-221.46\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"508.12,-224.84 516.09,-217.86 505.51,-218.34 508.12,-224.84\"/>\n",
       "</g>\n",
       "<!-- tv_spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>tv_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M400.8,-801.6C400.8,-801.6 343.95,-801.6 343.95,-801.6 337.95,-801.6 331.95,-795.6 331.95,-789.6 331.95,-789.6 331.95,-750 331.95,-750 331.95,-744 337.95,-738 343.95,-738 343.95,-738 400.8,-738 400.8,-738 406.8,-738 412.8,-744 412.8,-750 412.8,-750 412.8,-789.6 412.8,-789.6 412.8,-795.6 406.8,-801.6 400.8,-801.6\"/>\n",
       "<text text-anchor=\"start\" x=\"342.75\" y=\"-778.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-750.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M413.11,-751.65C423.14,-745.55 433.15,-737.93 440.55,-728.8 464.9,-698.78 442.8,-674.7 469.55,-646.8 472.28,-643.96 475.22,-641.31 478.34,-638.84\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"480.15,-641.84 486.3,-633.21 476.11,-636.13 480.15,-641.84\"/>\n",
       "</g>\n",
       "<!-- tv_spend_smoothed -->\n",
       "<g id=\"node17\" class=\"node\">\n",
       "<title>tv_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M637.4,-801.6C637.4,-801.6 507.8,-801.6 507.8,-801.6 501.8,-801.6 495.8,-795.6 495.8,-789.6 495.8,-789.6 495.8,-750 495.8,-750 495.8,-744 501.8,-738 507.8,-738 507.8,-738 637.4,-738 637.4,-738 643.4,-738 649.4,-744 649.4,-750 649.4,-750 649.4,-789.6 649.4,-789.6 649.4,-795.6 643.4,-801.6 637.4,-801.6\"/>\n",
       "<text text-anchor=\"start\" x=\"506.6\" y=\"-778.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-750.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;tv_spend_smoothed -->\n",
       "<g id=\"edge26\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;tv_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M413.01,-769.8C433.49,-769.8 459.34,-769.8 484.2,-769.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"484.01,-773.3 494.01,-769.8 484.01,-766.3 484.01,-773.3\"/>\n",
       "</g>\n",
       "<!-- total_marketing_spend&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>total_marketing_spend&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M657.93,-577.02C664.21,-573.37 670.21,-569.31 675.65,-564.8 708.7,-537.41 733.79,-495 749.36,-463.29\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"752.48,-464.88 753.62,-454.35 746.16,-461.87 752.48,-464.88\"/>\n",
       "</g>\n",
       "<!-- billboards_spend -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>billboards_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M427.05,-719.6C427.05,-719.6 317.7,-719.6 317.7,-719.6 311.7,-719.6 305.7,-713.6 305.7,-707.6 305.7,-707.6 305.7,-668 305.7,-668 305.7,-662 311.7,-656 317.7,-656 317.7,-656 427.05,-656 427.05,-656 433.05,-656 439.05,-662 439.05,-668 439.05,-668 439.05,-707.6 439.05,-707.6 439.05,-713.6 433.05,-719.6 427.05,-719.6\"/>\n",
       "<text text-anchor=\"start\" x=\"316.5\" y=\"-696.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-668.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M439.52,-659.39C449.57,-655.13 459.82,-650.83 469.55,-646.8 473.1,-645.33 476.72,-643.84 480.38,-642.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"481.43,-645.69 489.36,-638.67 478.78,-639.21 481.43,-645.69\"/>\n",
       "</g>\n",
       "<!-- billboards_spend_smoothed -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>billboards_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M663.65,-719.6C663.65,-719.6 481.55,-719.6 481.55,-719.6 475.55,-719.6 469.55,-713.6 469.55,-707.6 469.55,-707.6 469.55,-668 469.55,-668 469.55,-662 475.55,-656 481.55,-656 481.55,-656 663.65,-656 663.65,-656 669.65,-656 675.65,-662 675.65,-668 675.65,-668 675.65,-707.6 675.65,-707.6 675.65,-713.6 669.65,-719.6 663.65,-719.6\"/>\n",
       "<text text-anchor=\"start\" x=\"480.35\" y=\"-696.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-668.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;billboards_spend_smoothed -->\n",
       "<g id=\"edge19\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;billboards_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M439.38,-687.8C445.36,-687.8 451.53,-687.8 457.77,-687.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"457.57,-691.3 467.56,-687.8 457.56,-684.3 457.57,-691.3\"/>\n",
       "</g>\n",
       "<!-- twitter_spend -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>twitter_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M415.43,-555.6C415.43,-555.6 329.32,-555.6 329.32,-555.6 323.32,-555.6 317.32,-549.6 317.32,-543.6 317.32,-543.6 317.32,-504 317.32,-504 317.32,-498 323.32,-492 329.32,-492 329.32,-492 415.43,-492 415.43,-492 421.43,-492 427.43,-498 427.43,-504 427.43,-504 427.43,-543.6 427.43,-543.6 427.43,-549.6 421.43,-555.6 415.43,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"328.12\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M427.71,-547.2C441.35,-553.01 455.97,-559.18 469.55,-564.8 473.1,-566.27 476.72,-567.76 480.38,-569.26\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"478.78,-572.39 489.36,-572.93 481.43,-565.91 478.78,-572.39\"/>\n",
       "</g>\n",
       "<!-- twitter_spend_smoothed -->\n",
       "<g id=\"node20\" class=\"node\">\n",
       "<title>twitter_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M652.02,-473.6C652.02,-473.6 493.18,-473.6 493.18,-473.6 487.18,-473.6 481.18,-467.6 481.18,-461.6 481.18,-461.6 481.18,-422 481.18,-422 481.18,-416 487.18,-410 493.18,-410 493.18,-410 652.02,-410 652.02,-410 658.02,-410 664.02,-416 664.02,-422 664.02,-422 664.02,-461.6 664.02,-461.6 664.02,-467.6 658.02,-473.6 652.02,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"491.98\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;twitter_spend_smoothed -->\n",
       "<g id=\"edge29\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;twitter_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M427.71,-500.4C441.35,-494.59 455.97,-488.42 469.55,-482.8 473.1,-481.33 476.72,-479.84 480.38,-478.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"481.43,-481.69 489.36,-474.67 478.78,-475.21 481.43,-481.69\"/>\n",
       "</g>\n",
       "<!-- youtube_spend_smoothed -->\n",
       "<g id=\"node21\" class=\"node\">\n",
       "<title>youtube_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M657.65,-555.6C657.65,-555.6 487.55,-555.6 487.55,-555.6 481.55,-555.6 475.55,-549.6 475.55,-543.6 475.55,-543.6 475.55,-504 475.55,-504 475.55,-498 481.55,-492 487.55,-492 487.55,-492 657.65,-492 657.65,-492 663.65,-492 669.65,-498 669.65,-504 669.65,-504 669.65,-543.6 669.65,-543.6 669.65,-549.6 663.65,-555.6 657.65,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"486.35\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;youtube_spend_smoothed -->\n",
       "<g id=\"edge30\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;youtube_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M427.8,-523.8C439.12,-523.8 451.43,-523.8 463.91,-523.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"463.89,-527.3 473.89,-523.8 463.89,-520.3 463.89,-527.3\"/>\n",
       "</g>\n",
       "<!-- radio_spend_smoothed -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>radio_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M647.9,-309.6C647.9,-309.6 497.3,-309.6 497.3,-309.6 491.3,-309.6 485.3,-303.6 485.3,-297.6 485.3,-297.6 485.3,-258 485.3,-258 485.3,-252 491.3,-246 497.3,-246 497.3,-246 647.9,-246 647.9,-246 653.9,-246 659.9,-252 659.9,-258 659.9,-258 659.9,-297.6 659.9,-297.6 659.9,-303.6 653.9,-309.6 647.9,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"496.1\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_churn -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>womens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M421.43,-145.6C421.43,-145.6 323.32,-145.6 323.32,-145.6 317.32,-145.6 311.32,-139.6 311.32,-133.6 311.32,-133.6 311.32,-94 311.32,-94 311.32,-88 317.32,-82 323.32,-82 323.32,-82 421.43,-82 421.43,-82 427.43,-82 433.43,-88 433.43,-94 433.43,-94 433.43,-133.6 433.43,-133.6 433.43,-139.6 427.43,-145.6 421.43,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"322.12\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_churn -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>total_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M608.15,-145.6C608.15,-145.6 537.05,-145.6 537.05,-145.6 531.05,-145.6 525.05,-139.6 525.05,-133.6 525.05,-133.6 525.05,-94 525.05,-94 525.05,-88 531.05,-82 537.05,-82 537.05,-82 608.15,-82 608.15,-82 614.15,-82 620.15,-88 620.15,-94 620.15,-94 620.15,-133.6 620.15,-133.6 620.15,-139.6 614.15,-145.6 608.15,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"535.85\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_churn</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge22\" class=\"edge\">\n",
       "<title>womens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M433.66,-113.8C459.04,-113.8 488.46,-113.8 513.6,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"513.3,-117.3 523.3,-113.8 513.3,-110.3 513.3,-117.3\"/>\n",
       "</g>\n",
       "<!-- facebook_spend -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>facebook_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M424.43,-473.6C424.43,-473.6 320.32,-473.6 320.32,-473.6 314.32,-473.6 308.32,-467.6 308.32,-461.6 308.32,-461.6 308.32,-422 308.32,-422 308.32,-416 314.32,-410 320.32,-410 320.32,-410 424.43,-410 424.43,-410 430.43,-410 436.43,-416 436.43,-422 436.43,-422 436.43,-461.6 436.43,-461.6 436.43,-467.6 430.43,-473.6 424.43,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"319.12\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M432.27,-474.08C435.26,-476.82 438.05,-479.72 440.55,-482.8 464.9,-512.82 442.8,-536.9 469.55,-564.8 472.28,-567.64 475.22,-570.29 478.34,-572.76\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"476.11,-575.47 486.3,-578.39 480.15,-569.76 476.11,-575.47\"/>\n",
       "</g>\n",
       "<!-- facebook_spend_smoothed -->\n",
       "<g id=\"node22\" class=\"node\">\n",
       "<title>facebook_spend_smoothed</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M661.02,-391.6C661.02,-391.6 484.18,-391.6 484.18,-391.6 478.18,-391.6 472.18,-385.6 472.18,-379.6 472.18,-379.6 472.18,-340 472.18,-340 472.18,-334 478.18,-328 484.18,-328 484.18,-328 661.02,-328 661.02,-328 667.02,-328 673.02,-334 673.02,-340 673.02,-340 673.02,-379.6 673.02,-379.6 673.02,-385.6 667.02,-391.6 661.02,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"482.98\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"553.48\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;facebook_spend_smoothed -->\n",
       "<g id=\"edge31\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;facebook_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M436.67,-414.59C447.62,-409.95 458.9,-405.21 469.55,-400.8 473.1,-399.33 476.72,-397.84 480.38,-396.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"481.43,-399.69 489.36,-392.67 478.78,-393.21 481.43,-399.69\"/>\n",
       "</g>\n",
       "<!-- radio_spend -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>radio_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M411.3,-391.6C411.3,-391.6 333.45,-391.6 333.45,-391.6 327.45,-391.6 321.45,-385.6 321.45,-379.6 321.45,-379.6 321.45,-340 321.45,-340 321.45,-334 327.45,-328 333.45,-328 333.45,-328 411.3,-328 411.3,-328 417.3,-328 423.3,-334 423.3,-340 423.3,-340 423.3,-379.6 423.3,-379.6 423.3,-385.6 417.3,-391.6 411.3,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"332.25\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M423.75,-383.69C430.19,-388.57 436.08,-394.25 440.55,-400.8 482.28,-461.94 422.9,-507.33 469.55,-564.8 472.24,-568.11 475.23,-571.15 478.45,-573.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"476.2,-576.63 486.28,-579.89 480.43,-571.05 476.2,-576.63\"/>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;radio_spend_smoothed -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;radio_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M423.7,-338.11C438.45,-331.82 454.62,-324.98 469.55,-318.8 473.1,-317.33 476.72,-315.84 480.38,-314.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"481.43,-317.69 489.36,-310.67 478.78,-311.21 481.43,-317.69\"/>\n",
       "</g>\n",
       "<!-- total_churn&#45;&gt;total_customers -->\n",
       "<g id=\"edge25\" class=\"edge\">\n",
       "<title>total_churn&#45;&gt;total_customers</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M620.59,-123.72C642.57,-128.37 669.29,-134.01 693.88,-139.21\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"693.02,-142.6 703.53,-141.24 694.47,-135.75 693.02,-142.6\"/>\n",
       "</g>\n",
       "<!-- mens_churn -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>mens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M411.68,-63.6C411.68,-63.6 333.07,-63.6 333.07,-63.6 327.07,-63.6 321.07,-57.6 321.07,-51.6 321.07,-51.6 321.07,-12 321.07,-12 321.07,-6 327.07,0 333.07,0 333.07,0 411.68,0 411.68,0 417.68,0 423.68,-6 423.68,-12 423.68,-12 423.68,-51.6 423.68,-51.6 423.68,-57.6 417.68,-63.6 411.68,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"331.88\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- mens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge21\" class=\"edge\">\n",
       "<title>mens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M424.17,-52.81C451.63,-64.17 485.65,-78.24 514.08,-90.01\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"512.7,-93.22 523.28,-93.81 515.38,-86.76 512.7,-93.22\"/>\n",
       "</g>\n",
       "<!-- joined_data -->\n",
       "<g id=\"node18\" class=\"node\">\n",
       "<title>joined_data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M263.2,-432.6C263.2,-432.6 190.6,-432.6 190.6,-432.6 184.6,-432.6 178.6,-426.6 178.6,-420.6 178.6,-420.6 178.6,-381 178.6,-381 178.6,-375 184.6,-369 190.6,-369 190.6,-369 263.2,-369 263.2,-369 269.2,-369 275.2,-375 275.2,-381 275.2,-381 275.2,-420.6 275.2,-420.6 275.2,-426.6 269.2,-432.6 263.2,-432.6\"/>\n",
       "<text text-anchor=\"start\" x=\"189.4\" y=\"-409.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">joined_data</text>\n",
       "<text text-anchor=\"start\" x=\"192.77\" y=\"-381.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;youtube_spend -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;youtube_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M236.68,-432.94C247.7,-468.51 269.47,-525.92 304.2,-564.8 304.46,-565.09 304.71,-565.37 304.98,-565.66\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"302.41,-568.05 312.05,-572.45 307.26,-563 302.41,-568.05\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_signups -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M253.97,-368.85C267.93,-352.81 285.97,-333.68 304.2,-318.8 305.13,-318.04 306.07,-317.29 307.02,-316.54\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"308.75,-319.62 314.69,-310.85 304.57,-314 308.75,-319.62\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;tv_spend -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;tv_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M227.47,-433.02C228.21,-495.9 237.77,-636.86 304.2,-728.8 309.04,-735.5 315.35,-741.32 322.15,-746.31\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"320.12,-749.16 330.39,-751.76 323.98,-743.32 320.12,-749.16\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;billboards_spend -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;billboards_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M230.61,-432.83C236.34,-483.21 253.64,-581.89 304.2,-646.8 304.35,-647 304.51,-647.19 304.66,-647.38\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"301.93,-649.59 311.3,-654.52 307.05,-644.82 301.93,-649.59\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;twitter_spend -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;twitter_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M253.97,-432.75C267.93,-448.79 285.97,-467.92 304.2,-482.8 305.46,-483.83 306.74,-484.85 308.05,-485.86\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"305.6,-488.4 315.73,-491.49 309.74,-482.75 305.6,-488.4\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_churn -->\n",
       "<g id=\"edge17\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M230.61,-368.77C236.34,-318.39 253.64,-219.71 304.2,-154.8 304.35,-154.6 304.51,-154.41 304.66,-154.22\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"307.05,-156.78 311.3,-147.08 301.93,-152.01 307.05,-156.78\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;facebook_spend -->\n",
       "<g id=\"edge18\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;facebook_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M275.68,-414.45C282.55,-416.42 289.76,-418.48 297,-420.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"295.95,-423.89 306.52,-423.27 297.87,-417.16 295.95,-423.89\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;radio_spend -->\n",
       "<g id=\"edge20\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;radio_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M275.68,-387.15C286.79,-383.97 298.78,-380.54 310.39,-377.23\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"311.24,-380.62 319.9,-374.51 309.32,-373.89 311.24,-380.62\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_churn -->\n",
       "<g id=\"edge23\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M227.47,-368.58C228.21,-305.7 237.77,-164.74 304.2,-72.8 306.51,-69.6 309.15,-66.6 312.03,-63.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"314.18,-66.57 319.49,-57.4 309.62,-61.25 314.18,-66.57\"/>\n",
       "</g>\n",
       "<!-- mens_signups -->\n",
       "<g id=\"node19\" class=\"node\">\n",
       "<title>mens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M418.8,-227.6C418.8,-227.6 325.95,-227.6 325.95,-227.6 319.95,-227.6 313.95,-221.6 313.95,-215.6 313.95,-215.6 313.95,-176 313.95,-176 313.95,-170 319.95,-164 325.95,-164 325.95,-164 418.8,-164 418.8,-164 424.8,-164 430.8,-170 430.8,-176 430.8,-176 430.8,-215.6 430.8,-215.6 430.8,-221.6 424.8,-227.6 418.8,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"324.75\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"353.25\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_signups -->\n",
       "<g id=\"edge28\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M236.68,-368.66C247.7,-333.09 269.47,-275.68 304.2,-236.8 304.55,-236.41 304.91,-236.01 305.27,-235.62\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"307.54,-238.3 312.36,-228.87 302.71,-233.23 307.54,-238.3\"/>\n",
       "</g>\n",
       "<!-- mens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>mens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M431.24,-195.8C454.82,-195.8 482.19,-195.8 506.46,-195.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"506.22,-199.3 516.22,-195.8 506.22,-192.3 506.22,-199.3\"/>\n",
       "</g>\n",
       "<!-- _joined_data_inputs -->\n",
       "<g id=\"node23\" class=\"node\">\n",
       "<title>_joined_data_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"149.6,-444.1 0,-444.1 0,-357.5 149.6,-357.5 149.6,-444.1\"/>\n",
       "<text text-anchor=\"start\" x=\"14.55\" y=\"-416\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"66.67\" y=\"-416\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">DataFrame</text>\n",
       "<text text-anchor=\"start\" x=\"19.42\" y=\"-395\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"66.67\" y=\"-395\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">DataFrame</text>\n",
       "<text text-anchor=\"start\" x=\"20.92\" y=\"-374\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"66.67\" y=\"-374\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- _joined_data_inputs&#45;&gt;joined_data -->\n",
       "<g id=\"edge27\" class=\"edge\">\n",
       "<title>_joined_data_inputs&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M149.97,-400.8C155.67,-400.8 161.38,-400.8 166.96,-400.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"166.69,-404.3 176.69,-400.8 166.69,-397.3 166.69,-404.3\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node24\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"101.8,-499.1 47.8,-499.1 47.8,-462.5 101.8,-462.5 101.8,-499.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"74.8\" y=\"-475\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node25\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M97.22,-554.1C97.22,-554.1 52.37,-554.1 52.37,-554.1 46.37,-554.1 40.37,-548.1 40.37,-542.1 40.37,-542.1 40.37,-529.5 40.37,-529.5 40.37,-523.5 46.37,-517.5 52.37,-517.5 52.37,-517.5 97.22,-517.5 97.22,-517.5 103.22,-517.5 109.22,-523.5 109.22,-529.5 109.22,-529.5 109.22,-542.1 109.22,-542.1 109.22,-548.1 103.22,-554.1 97.22,-554.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"74.8\" y=\"-530\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e1a23d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module prep_data --display\n",
    "# Preparing the data\n",
    "import pandas as pd\n",
    "from hamilton.function_modifiers import does, extract_columns, parameterize, source, value\n",
    "\n",
    "def _sum_series(**series):\n",
    "    return sum(series.values())\n",
    "\n",
    "\n",
    "@extract_columns(\n",
    "    \"facebook_spend\",\n",
    "    \"twitter_spend\",\n",
    "    \"tv_spend\",\n",
    "    \"youtube_spend\",\n",
    "    \"radio_spend\",\n",
    "    \"billboards_spend\",\n",
    "    \"womens_churn\",\n",
    "    \"mens_churn\",\n",
    "    \"womens_signups\",\n",
    "    \"mens_signups\",\n",
    ")\n",
    "def joined_data(spend: pd.DataFrame, signups: pd.DataFrame, churn: pd.DataFrame) -> pd.DataFrame:\n",
    "    spend = spend.set_index(\"date\").rename(columns=lambda col: col + \"_spend\")\n",
    "    churn = churn.set_index(\"date\").rename(columns=lambda col: col + \"_churn\")\n",
    "    signups = signups.set_index(\"date\").rename(columns=lambda col: col + \"_signups\")\n",
    "    return pd.concat([spend, churn, signups], axis=1)\n",
    "\n",
    "\n",
    "@does(_sum_series)\n",
    "def total_marketing_spend(\n",
    "    facebook_spend: pd.Series,\n",
    "    twitter_spend: pd.Series,\n",
    "    tv_spend: pd.Series,\n",
    "    youtube_spend: pd.Series,\n",
    "    radio_spend: pd.Series,\n",
    "    billboards_spend: pd.Series,\n",
    ") -> pd.Series:\n",
    "    pass\n",
    "\n",
    "\n",
    "@does(_sum_series)\n",
    "def total_signups(mens_signups: pd.Series, womens_signups: pd.Series) -> pd.Series:\n",
    "    pass\n",
    "\n",
    "\n",
    "@does(_sum_series)\n",
    "def total_churn(mens_churn: pd.Series, womens_churn: pd.Series) -> pd.Series:\n",
    "    pass\n",
    "\n",
    "\n",
    "def total_customers(total_signups: pd.Series, total_churn: pd.Series) -> pd.Series:\n",
    "    customer_deltas = total_signups + total_churn\n",
    "    return customer_deltas.cumsum()\n",
    "\n",
    "\n",
    "def acquisition_cost(total_marketing_spend: pd.Series, total_signups: pd.Series) -> pd.Series:\n",
    "    return total_marketing_spend / total_signups\n",
    "\n",
    "\n",
    "@parameterize(\n",
    "    twitter_spend_smoothed={\"lookback_days\": value(7), \"spend\": source(\"twitter_spend\")},\n",
    "    facebook_spend_smoothed={\"lookback_days\": value(7), \"spend\": source(\"facebook_spend\")},\n",
    "    radio_spend_smoothed={\"lookback_days\": value(21), \"spend\": source(\"radio_spend\")},\n",
    "    tv_spend_smoothed={\"lookback_days\": value(21), \"spend\": source(\"tv_spend\")},\n",
    "    billboards_spend_smoothed={\"lookback_days\": value(7), \"spend\": source(\"billboards_spend\")},\n",
    "    youtube_spend_smoothed={\"lookback_days\": value(7), \"spend\": source(\"twitter_spend\")},\n",
    ")\n",
    "def spend_smoothed(lookback_days: int, spend: pd.Series) -> pd.Series:\n",
    "    \"\"\"{spend} smoothed by {lookback_days}. Might want to smooth different ad spends differently,\n",
    "    figuring that it takes different amounts of time to get to the customer. A cheap hack at determining\n",
    "    auto-correlation of a series -- this should be a parameter in a model,\n",
    "    but this is to demonstrate the framework\n",
    "\n",
    "    :param lookback_days: Days to smooth over\n",
    "    :param spend: Spend source\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    return spend.rolling(window=lookback_days).mean().fillna(0)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Execution for the three data loaders"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "VARS = [\n",
    "    \"total_signups\",\n",
    "    \"total_churn\",\n",
    "    \"total_marketing_spend\",\n",
    "    \"acquisition_cost\",\n",
    "    \"twitter_spend_smoothed\",\n",
    "    \"facebook_spend_smoothed\",\n",
    "    \"radio_spend_smoothed\",\n",
    "    \"tv_spend_smoothed\",\n",
    "    \"billboards_spend_smoothed\",\n",
    "    \"youtube_spend_smoothed\",\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"1094pt\" height=\"892pt\"\n",
       " viewBox=\"0.00 0.00 1094.20 891.60\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 887.6)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-887.6 1090.2,-887.6 1090.2,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-515.8 8,-700.8 92.85,-700.8 92.85,-515.8 8,-515.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-683.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- youtube_spend -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>youtube_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M674.5,-309.6C674.5,-309.6 577.15,-309.6 577.15,-309.6 571.15,-309.6 565.15,-303.6 565.15,-297.6 565.15,-297.6 565.15,-258 565.15,-258 565.15,-252 571.15,-246 577.15,-246 577.15,-246 674.5,-246 674.5,-246 680.5,-246 686.5,-252 686.5,-258 686.5,-258 686.5,-297.6 686.5,-297.6 686.5,-303.6 680.5,-309.6 674.5,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"575.95\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_marketing_spend -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>total_marketing_spend</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M899.1,-309.6C899.1,-309.6 753,-309.6 753,-309.6 747,-309.6 741,-303.6 741,-297.6 741,-297.6 741,-258 741,-258 741,-252 747,-246 753,-246 753,-246 899.1,-246 899.1,-246 905.1,-246 911.1,-252 911.1,-258 911.1,-258 911.1,-297.6 911.1,-297.6 911.1,-303.6 905.1,-309.6 899.1,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"751.8\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_marketing_spend</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- youtube_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge18\" class=\"edge\">\n",
       "<title>youtube_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M686.84,-277.8C700.37,-277.8 715.05,-277.8 729.64,-277.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"729.23,-281.3 739.23,-277.8 729.23,-274.3 729.23,-281.3\"/>\n",
       "</g>\n",
       "<!-- total_signups -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>total_signups</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M868.73,-637.6C868.73,-637.6 783.38,-637.6 783.38,-637.6 777.38,-637.6 771.38,-631.6 771.38,-625.6 771.38,-625.6 771.38,-586 771.38,-586 771.38,-580 777.38,-574 783.38,-574 783.38,-574 868.73,-574 868.73,-574 874.73,-574 880.73,-580 880.73,-586 880.73,-586 880.73,-625.6 880.73,-625.6 880.73,-631.6 874.73,-637.6 868.73,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"782.18\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_signups</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- acquisition_cost -->\n",
       "<g id=\"node24\" class=\"node\">\n",
       "<title>acquisition_cost</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1074.2,-473.6C1074.2,-473.6 970.1,-473.6 970.1,-473.6 964.1,-473.6 958.1,-467.6 958.1,-461.6 958.1,-461.6 958.1,-422 958.1,-422 958.1,-416 964.1,-410 970.1,-410 970.1,-410 1074.2,-410 1074.2,-410 1080.2,-410 1086.2,-416 1086.2,-422 1086.2,-422 1086.2,-461.6 1086.2,-461.6 1086.2,-467.6 1080.2,-473.6 1074.2,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"968.9\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">acquisition_cost</text>\n",
       "<text text-anchor=\"start\" x=\"1003.03\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_signups&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge34\" class=\"edge\">\n",
       "<title>total_signups&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M881.09,-590.36C897.52,-584.08 914.94,-575.68 929.1,-564.8 957.61,-542.9 981.61,-509.96 997.95,-483.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1000.86,-485.64 1003.05,-475.27 994.87,-482.01 1000.86,-485.64\"/>\n",
       "</g>\n",
       "<!-- womens_churn -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>womens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M674.88,-883.6C674.88,-883.6 576.78,-883.6 576.78,-883.6 570.78,-883.6 564.78,-877.6 564.78,-871.6 564.78,-871.6 564.78,-832 564.78,-832 564.78,-826 570.78,-820 576.78,-820 576.78,-820 674.88,-820 674.88,-820 680.88,-820 686.88,-826 686.88,-832 686.88,-832 686.88,-871.6 686.88,-871.6 686.88,-877.6 680.88,-883.6 674.88,-883.6\"/>\n",
       "<text text-anchor=\"start\" x=\"575.58\" y=\"-860.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-832.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_churn -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>total_churn</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M861.6,-842.6C861.6,-842.6 790.5,-842.6 790.5,-842.6 784.5,-842.6 778.5,-836.6 778.5,-830.6 778.5,-830.6 778.5,-791 778.5,-791 778.5,-785 784.5,-779 790.5,-779 790.5,-779 861.6,-779 861.6,-779 867.6,-779 873.6,-785 873.6,-791 873.6,-791 873.6,-830.6 873.6,-830.6 873.6,-836.6 867.6,-842.6 861.6,-842.6\"/>\n",
       "<text text-anchor=\"start\" x=\"789.3\" y=\"-819.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_churn</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-791.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>womens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M687.11,-839.33C712.49,-834.08 741.91,-828 767.05,-822.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"767.7,-826.24 776.78,-820.78 766.28,-819.38 767.7,-826.24\"/>\n",
       "</g>\n",
       "<!-- facebook_spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>facebook_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M677.88,-555.6C677.88,-555.6 573.78,-555.6 573.78,-555.6 567.78,-555.6 561.78,-549.6 561.78,-543.6 561.78,-543.6 561.78,-504 561.78,-504 561.78,-498 567.78,-492 573.78,-492 573.78,-492 677.88,-492 677.88,-492 683.88,-492 689.88,-498 689.88,-504 689.88,-504 689.88,-543.6 689.88,-543.6 689.88,-549.6 683.88,-555.6 677.88,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"572.58\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M686.63,-491.68C689.35,-488.92 691.84,-485.96 694,-482.8 735.73,-421.66 676.35,-376.27 723,-318.8 725.69,-315.49 728.68,-312.45 731.9,-309.65\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"733.88,-312.55 739.73,-303.71 729.65,-306.97 733.88,-312.55\"/>\n",
       "</g>\n",
       "<!-- facebook_spend_smoothed -->\n",
       "<g id=\"node23\" class=\"node\">\n",
       "<title>facebook_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M914.48,-555.6C914.48,-555.6 737.63,-555.6 737.63,-555.6 731.63,-555.6 725.63,-549.6 725.63,-543.6 725.63,-543.6 725.63,-504 725.63,-504 725.63,-498 731.63,-492 737.63,-492 737.63,-492 914.48,-492 914.48,-492 920.48,-492 926.48,-498 926.48,-504 926.48,-504 926.48,-543.6 926.48,-543.6 926.48,-549.6 920.48,-555.6 914.48,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"736.43\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;facebook_spend_smoothed -->\n",
       "<g id=\"edge32\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;facebook_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M690.36,-523.8C697.98,-523.8 705.93,-523.8 713.98,-523.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"713.89,-527.3 723.89,-523.8 713.89,-520.3 713.89,-527.3\"/>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-596.6C391.05,-596.6 325.2,-596.6 325.2,-596.6 319.2,-596.6 313.2,-590.6 313.2,-584.6 313.2,-584.6 313.2,-545 313.2,-545 313.2,-539 319.2,-533 325.2,-533 325.2,-533 391.05,-533 391.05,-533 397.05,-533 403.05,-539 403.05,-545 403.05,-545 403.05,-584.6 403.05,-584.6 403.05,-590.6 397.05,-596.6 391.05,-596.6\"/>\n",
       "<text text-anchor=\"start\" x=\"338.25\" y=\"-573.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-545.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- joined_data -->\n",
       "<g id=\"node16\" class=\"node\">\n",
       "<title>joined_data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M516.65,-514.6C516.65,-514.6 444.05,-514.6 444.05,-514.6 438.05,-514.6 432.05,-508.6 432.05,-502.6 432.05,-502.6 432.05,-463 432.05,-463 432.05,-457 438.05,-451 444.05,-451 444.05,-451 516.65,-451 516.65,-451 522.65,-451 528.65,-457 528.65,-463 528.65,-463 528.65,-502.6 528.65,-502.6 528.65,-508.6 522.65,-514.6 516.65,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"442.85\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">joined_data</text>\n",
       "<text text-anchor=\"start\" x=\"446.23\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend&#45;&gt;joined_data -->\n",
       "<g id=\"edge23\" class=\"edge\">\n",
       "<title>spend&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M403.21,-534.73C409.51,-530.43 416.07,-525.96 422.58,-521.52\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"424.49,-524.45 430.78,-515.93 420.55,-518.67 424.49,-524.45\"/>\n",
       "</g>\n",
       "<!-- womens_signups -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>womens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M682,-719.6C682,-719.6 569.65,-719.6 569.65,-719.6 563.65,-719.6 557.65,-713.6 557.65,-707.6 557.65,-707.6 557.65,-668 557.65,-668 557.65,-662 563.65,-656 569.65,-656 569.65,-656 682,-656 682,-656 688,-656 694,-662 694,-668 694,-668 694,-707.6 694,-707.6 694,-713.6 688,-719.6 682,-719.6\"/>\n",
       "<text text-anchor=\"start\" x=\"568.45\" y=\"-696.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-668.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>womens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M694.49,-659.81C715.88,-650.96 739.46,-641.21 760.62,-632.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"761.82,-635.74 769.72,-628.69 759.15,-629.28 761.82,-635.74\"/>\n",
       "</g>\n",
       "<!-- billboards_spend_smoothed -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>billboards_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M917.1,-227.6C917.1,-227.6 735,-227.6 735,-227.6 729,-227.6 723,-221.6 723,-215.6 723,-215.6 723,-176 723,-176 723,-170 729,-164 735,-164 735,-164 917.1,-164 917.1,-164 923.1,-164 929.1,-170 929.1,-176 929.1,-176 929.1,-215.6 929.1,-215.6 929.1,-221.6 923.1,-227.6 917.1,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"733.8\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>radio_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M664.75,-473.6C664.75,-473.6 586.9,-473.6 586.9,-473.6 580.9,-473.6 574.9,-467.6 574.9,-461.6 574.9,-461.6 574.9,-422 574.9,-422 574.9,-416 580.9,-410 586.9,-410 586.9,-410 664.75,-410 664.75,-410 670.75,-410 676.75,-416 676.75,-422 676.75,-422 676.75,-461.6 676.75,-461.6 676.75,-467.6 670.75,-473.6 664.75,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"585.7\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge19\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M676.94,-416.71C683.26,-412.05 689.18,-406.74 694,-400.8 718.35,-370.78 696.25,-346.7 723,-318.8 725.73,-315.96 728.67,-313.31 731.79,-310.84\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"733.6,-313.84 739.75,-305.21 729.56,-308.13 733.6,-313.84\"/>\n",
       "</g>\n",
       "<!-- radio_spend_smoothed -->\n",
       "<g id=\"node25\" class=\"node\">\n",
       "<title>radio_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M901.35,-473.6C901.35,-473.6 750.75,-473.6 750.75,-473.6 744.75,-473.6 738.75,-467.6 738.75,-461.6 738.75,-461.6 738.75,-422 738.75,-422 738.75,-416 744.75,-410 750.75,-410 750.75,-410 901.35,-410 901.35,-410 907.35,-410 913.35,-416 913.35,-422 913.35,-422 913.35,-461.6 913.35,-461.6 913.35,-467.6 907.35,-473.6 901.35,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"749.55\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;radio_spend_smoothed -->\n",
       "<g id=\"edge35\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;radio_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M677.1,-441.8C692.44,-441.8 709.85,-441.8 727.22,-441.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"727.09,-445.3 737.09,-441.8 727.09,-438.3 727.09,-445.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>tv_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M654.25,-391.6C654.25,-391.6 597.4,-391.6 597.4,-391.6 591.4,-391.6 585.4,-385.6 585.4,-379.6 585.4,-379.6 585.4,-340 585.4,-340 585.4,-334 591.4,-328 597.4,-328 597.4,-328 654.25,-328 654.25,-328 660.25,-328 666.25,-334 666.25,-340 666.25,-340 666.25,-379.6 666.25,-379.6 666.25,-385.6 660.25,-391.6 654.25,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"596.2\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend_smoothed -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>tv_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M890.85,-391.6C890.85,-391.6 761.25,-391.6 761.25,-391.6 755.25,-391.6 749.25,-385.6 749.25,-379.6 749.25,-379.6 749.25,-340 749.25,-340 749.25,-334 755.25,-328 761.25,-328 761.25,-328 890.85,-328 890.85,-328 896.85,-328 902.85,-334 902.85,-340 902.85,-340 902.85,-379.6 902.85,-379.6 902.85,-385.6 896.85,-391.6 890.85,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"760.05\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;tv_spend_smoothed -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;tv_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M666.46,-359.8C686.94,-359.8 712.79,-359.8 737.65,-359.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"737.46,-363.3 747.46,-359.8 737.46,-356.3 737.46,-363.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge17\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M666.52,-342.66C683.83,-335.24 704.38,-326.51 723,-318.8 726.55,-317.33 730.17,-315.84 733.83,-314.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"734.88,-317.69 742.81,-310.67 732.23,-311.21 734.88,-317.69\"/>\n",
       "</g>\n",
       "<!-- mens_churn -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>mens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M665.12,-801.6C665.12,-801.6 586.53,-801.6 586.53,-801.6 580.53,-801.6 574.53,-795.6 574.53,-789.6 574.53,-789.6 574.53,-750 574.53,-750 574.53,-744 580.53,-738 586.53,-738 586.53,-738 665.12,-738 665.12,-738 671.12,-738 677.12,-744 677.12,-750 677.12,-750 677.12,-789.6 677.12,-789.6 677.12,-795.6 671.12,-801.6 665.12,-801.6\"/>\n",
       "<text text-anchor=\"start\" x=\"585.33\" y=\"-778.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-750.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- mens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>mens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M677.62,-780.31C704.96,-785.96 738.8,-792.96 767.16,-798.83\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"766.15,-802.19 776.65,-800.79 767.57,-795.34 766.15,-802.19\"/>\n",
       "</g>\n",
       "<!-- total_marketing_spend&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge33\" class=\"edge\">\n",
       "<title>total_marketing_spend&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M911.54,-307.32C917.71,-310.79 923.65,-314.61 929.1,-318.8 957.61,-340.7 981.61,-373.64 997.95,-399.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"994.87,-401.59 1003.05,-408.33 1000.86,-397.96 994.87,-401.59\"/>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-514.6C391.05,-514.6 325.2,-514.6 325.2,-514.6 319.2,-514.6 313.2,-508.6 313.2,-502.6 313.2,-502.6 313.2,-463 313.2,-463 313.2,-457 319.2,-451 325.2,-451 325.2,-451 391.05,-451 391.05,-451 397.05,-451 403.05,-457 403.05,-463 403.05,-463 403.05,-502.6 403.05,-502.6 403.05,-508.6 397.05,-514.6 391.05,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"332.25\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- signups&#45;&gt;joined_data -->\n",
       "<g id=\"edge24\" class=\"edge\">\n",
       "<title>signups&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M403.21,-482.8C408.85,-482.8 414.68,-482.8 420.51,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"420.11,-486.3 430.11,-482.8 420.11,-479.3 420.11,-486.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>billboards_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M680.5,-227.6C680.5,-227.6 571.15,-227.6 571.15,-227.6 565.15,-227.6 559.15,-221.6 559.15,-215.6 559.15,-215.6 559.15,-176 559.15,-176 559.15,-170 565.15,-164 571.15,-164 571.15,-164 680.5,-164 680.5,-164 686.5,-164 692.5,-170 692.5,-176 692.5,-176 692.5,-215.6 692.5,-215.6 692.5,-221.6 686.5,-227.6 680.5,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"569.95\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;billboards_spend_smoothed -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;billboards_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M692.83,-195.8C698.81,-195.8 704.98,-195.8 711.22,-195.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"711.02,-199.3 721.01,-195.8 711.01,-192.3 711.02,-199.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge20\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M692.97,-224.21C703.02,-228.47 713.27,-232.77 723,-236.8 726.55,-238.27 730.17,-239.76 733.83,-241.26\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"732.23,-244.39 742.81,-244.93 734.88,-237.91 732.23,-244.39\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;youtube_spend -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;youtube_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M490.13,-450.66C501.15,-415.09 522.92,-357.68 557.65,-318.8 557.91,-318.51 558.16,-318.23 558.43,-317.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"560.71,-320.6 565.5,-311.15 555.86,-315.55 560.71,-320.6\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_churn -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M480.92,-515.02C481.66,-577.9 491.22,-718.86 557.65,-810.8 557.72,-810.9 557.79,-810.99 557.86,-811.09\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"555.02,-813.16 564.22,-818.4 560.3,-808.56 555.02,-813.16\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;facebook_spend -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;facebook_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M529.13,-496.45C536,-498.42 543.21,-500.48 550.45,-502.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"549.4,-505.89 559.97,-505.27 551.32,-499.16 549.4,-505.89\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_signups -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M490.13,-514.94C501.15,-550.51 522.92,-607.92 557.65,-646.8 557.91,-647.09 558.16,-647.37 558.43,-647.66\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"555.86,-650.05 565.5,-654.45 560.71,-645 555.86,-650.05\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;radio_spend -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;radio_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M529.13,-469.15C540.24,-465.97 552.23,-462.54 563.84,-459.23\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"564.69,-462.62 573.35,-456.51 562.77,-455.89 564.69,-462.62\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;tv_spend -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;tv_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M507.42,-450.85C521.38,-434.81 539.42,-415.68 557.65,-400.8 563.34,-396.16 569.6,-391.65 575.94,-387.44\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"577.43,-390.65 583.96,-382.3 573.65,-384.75 577.43,-390.65\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_churn -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M484.06,-514.83C489.79,-565.21 507.09,-663.89 557.65,-728.8 560.03,-731.86 562.71,-734.74 565.59,-737.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"563.09,-739.92 573,-743.66 567.58,-734.55 563.09,-739.92\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;billboards_spend -->\n",
       "<g id=\"edge22\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;billboards_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M484.06,-450.77C489.79,-400.39 507.09,-301.71 557.65,-236.8 557.8,-236.6 557.96,-236.41 558.11,-236.22\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"560.5,-238.78 564.75,-229.08 555.38,-234.01 560.5,-238.78\"/>\n",
       "</g>\n",
       "<!-- mens_signups -->\n",
       "<g id=\"node17\" class=\"node\">\n",
       "<title>mens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M672.25,-637.6C672.25,-637.6 579.4,-637.6 579.4,-637.6 573.4,-637.6 567.4,-631.6 567.4,-625.6 567.4,-625.6 567.4,-586 567.4,-586 567.4,-580 573.4,-574 579.4,-574 579.4,-574 672.25,-574 672.25,-574 678.25,-574 684.25,-580 684.25,-586 684.25,-586 684.25,-625.6 684.25,-625.6 684.25,-631.6 678.25,-637.6 672.25,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"578.2\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_signups -->\n",
       "<g id=\"edge26\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M507.42,-514.75C521.38,-530.79 539.42,-549.92 557.65,-564.8 558.58,-565.56 559.52,-566.31 560.47,-567.06\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"558.02,-569.6 568.14,-572.75 562.2,-563.98 558.02,-569.6\"/>\n",
       "</g>\n",
       "<!-- twitter_spend -->\n",
       "<g id=\"node22\" class=\"node\">\n",
       "<title>twitter_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M668.88,-145.6C668.88,-145.6 582.78,-145.6 582.78,-145.6 576.78,-145.6 570.78,-139.6 570.78,-133.6 570.78,-133.6 570.78,-94 570.78,-94 570.78,-88 576.78,-82 582.78,-82 582.78,-82 668.88,-82 668.88,-82 674.88,-82 680.88,-88 680.88,-94 680.88,-94 680.88,-133.6 680.88,-133.6 680.88,-139.6 674.88,-145.6 668.88,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"581.58\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend</text>\n",
       "<text text-anchor=\"start\" x=\"606.7\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;twitter_spend -->\n",
       "<g id=\"edge31\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;twitter_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M480.92,-450.58C481.66,-387.7 491.22,-246.74 557.65,-154.8 559.11,-152.78 560.71,-150.83 562.41,-148.97\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"564.55,-151.76 569.39,-142.33 559.73,-146.69 564.55,-151.76\"/>\n",
       "</g>\n",
       "<!-- mens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>mens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M684.69,-605.8C708.27,-605.8 735.64,-605.8 759.91,-605.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"759.67,-609.3 769.67,-605.8 759.67,-602.3 759.67,-609.3\"/>\n",
       "</g>\n",
       "<!-- connection -->\n",
       "<g id=\"node18\" class=\"node\">\n",
       "<title>connection</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M272.2,-514.6C272.2,-514.6 141.1,-514.6 141.1,-514.6 135.1,-514.6 129.1,-508.6 129.1,-502.6 129.1,-502.6 129.1,-463 129.1,-463 129.1,-457 135.1,-451 141.1,-451 141.1,-451 272.2,-451 272.2,-451 278.2,-451 284.2,-457 284.2,-463 284.2,-463 284.2,-502.6 284.2,-502.6 284.2,-508.6 278.2,-514.6 272.2,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"170.65\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">connection</text>\n",
       "<text text-anchor=\"start\" x=\"139.9\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DuckDBPyConnection</text>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;spend -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>connection&#45;&gt;spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M266.3,-514.97C278.44,-521.63 291.17,-528.62 303.14,-535.18\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"301.2,-538.11 311.65,-539.85 304.57,-531.97 301.2,-538.11\"/>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;signups -->\n",
       "<g id=\"edge21\" class=\"edge\">\n",
       "<title>connection&#45;&gt;signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M284.58,-482.8C290.35,-482.8 296.11,-482.8 301.72,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"301.44,-486.3 311.44,-482.8 301.44,-479.3 301.44,-486.3\"/>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node20\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M391.05,-432.6C391.05,-432.6 325.2,-432.6 325.2,-432.6 319.2,-432.6 313.2,-426.6 313.2,-420.6 313.2,-420.6 313.2,-381 313.2,-381 313.2,-375 319.2,-369 325.2,-369 325.2,-369 391.05,-369 391.05,-369 397.05,-369 403.05,-375 403.05,-381 403.05,-381 403.05,-420.6 403.05,-420.6 403.05,-426.6 397.05,-432.6 391.05,-432.6\"/>\n",
       "<text text-anchor=\"start\" x=\"339.38\" y=\"-409.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"324\" y=\"-381.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- connection&#45;&gt;churn -->\n",
       "<g id=\"edge29\" class=\"edge\">\n",
       "<title>connection&#45;&gt;churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M266.3,-450.63C278.44,-443.97 291.17,-436.98 303.14,-430.42\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"304.57,-433.63 311.65,-425.75 301.2,-427.49 304.57,-433.63\"/>\n",
       "</g>\n",
       "<!-- twitter_spend_smoothed -->\n",
       "<g id=\"node19\" class=\"node\">\n",
       "<title>twitter_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M905.48,-63.6C905.48,-63.6 746.63,-63.6 746.63,-63.6 740.63,-63.6 734.63,-57.6 734.63,-51.6 734.63,-51.6 734.63,-12 734.63,-12 734.63,-6 740.63,0 746.63,0 746.63,0 905.48,0 905.48,0 911.48,0 917.48,-6 917.48,-12 917.48,-12 917.48,-51.6 917.48,-51.6 917.48,-57.6 911.48,-63.6 905.48,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"745.43\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- churn&#45;&gt;joined_data -->\n",
       "<g id=\"edge25\" class=\"edge\">\n",
       "<title>churn&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M403.21,-430.87C409.51,-435.17 416.07,-439.64 422.58,-444.08\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"420.55,-446.93 430.78,-449.67 424.49,-441.15 420.55,-446.93\"/>\n",
       "</g>\n",
       "<!-- youtube_spend_smoothed -->\n",
       "<g id=\"node21\" class=\"node\">\n",
       "<title>youtube_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M911.1,-145.6C911.1,-145.6 741,-145.6 741,-145.6 735,-145.6 729,-139.6 729,-133.6 729,-133.6 729,-94 729,-94 729,-88 735,-82 741,-82 741,-82 911.1,-82 911.1,-82 917.1,-82 923.1,-88 923.1,-94 923.1,-94 923.1,-133.6 923.1,-133.6 923.1,-139.6 917.1,-145.6 911.1,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"739.8\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"806.93\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M681.27,-142.24C685.95,-146.05 690.3,-150.24 694,-154.8 718.35,-184.82 696.25,-208.9 723,-236.8 725.73,-239.64 728.67,-242.29 731.79,-244.76\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"729.56,-247.47 739.75,-250.39 733.6,-241.76 729.56,-247.47\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;twitter_spend_smoothed -->\n",
       "<g id=\"edge28\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;twitter_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M681.16,-90.4C694.8,-84.59 709.42,-78.42 723,-72.8 726.55,-71.33 730.17,-69.84 733.83,-68.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"734.88,-71.69 742.81,-64.67 732.23,-65.21 734.88,-71.69\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;youtube_spend_smoothed -->\n",
       "<g id=\"edge30\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;youtube_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M681.25,-113.8C692.57,-113.8 704.88,-113.8 717.36,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"717.34,-117.3 727.34,-113.8 717.34,-110.3 717.34,-117.3\"/>\n",
       "</g>\n",
       "<!-- _connection_inputs -->\n",
       "<g id=\"node26\" class=\"node\">\n",
       "<title>_connection_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"100.1,-505.1 0.75,-505.1 0.75,-460.5 100.1,-460.5 100.1,-505.1\"/>\n",
       "<text text-anchor=\"start\" x=\"15.55\" y=\"-477\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">db_path</text>\n",
       "<text text-anchor=\"start\" x=\"70.3\" y=\"-477\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _connection_inputs&#45;&gt;connection -->\n",
       "<g id=\"edge27\" class=\"edge\">\n",
       "<title>_connection_inputs&#45;&gt;connection</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M100.22,-482.8C105.76,-482.8 111.53,-482.8 117.38,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"117.19,-486.3 127.19,-482.8 117.19,-479.3 117.19,-486.3\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node27\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"77.42,-560.1 23.42,-560.1 23.42,-523.5 77.42,-523.5 77.42,-560.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-536\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node28\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-615.1C72.85,-615.1 28,-615.1 28,-615.1 22,-615.1 16,-609.1 16,-603.1 16,-603.1 16,-590.5 16,-590.5 16,-584.5 22,-578.5 28,-578.5 28,-578.5 72.85,-578.5 72.85,-578.5 78.85,-578.5 84.85,-584.5 84.85,-590.5 84.85,-590.5 84.85,-603.1 84.85,-603.1 84.85,-609.1 78.85,-615.1 72.85,-615.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-591\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- output -->\n",
       "<g id=\"node29\" class=\"node\">\n",
       "<title>output</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M67.97,-670.1C67.97,-670.1 32.87,-670.1 32.87,-670.1 26.87,-670.1 20.87,-664.1 20.87,-658.1 20.87,-658.1 20.87,-645.5 20.87,-645.5 20.87,-639.5 26.87,-633.5 32.87,-633.5 32.87,-633.5 67.97,-633.5 67.97,-633.5 73.97,-633.5 79.97,-639.5 79.97,-645.5 79.97,-645.5 79.97,-658.1 79.97,-658.1 79.97,-664.1 73.97,-670.1 67.97,-670.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-646\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">output</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e1a75b0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Execution for duckdb data\n",
    "\n",
    "driver = (hamilton.driver.Builder()\n",
    "          .with_modules(load_data_duckdb, prep_data)\n",
    "          .with_adapters(base.PandasDataFrameResult())\n",
    "          .build()\n",
    ")\n",
    "# Uncomment the print function below to display the execution result when have manually handled connections/whatnot for duckdb\n",
    "# print(driver.execute(VARS)) \n",
    "\n",
    "duckdb_execution_graph = driver.visualize_execution(VARS, inputs={\"db_path\": \"./test_data/database.duckdb\"})\n",
    "display(duckdb_execution_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'keep_date_col' keyword in pd.read_csv is deprecated and will be removed in a future version. Explicitly remove unwanted columns after parsing instead.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'verbose' keyword in pd.read_csv is deprecated and will be removed in a future version.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'keep_date_col' keyword in pd.read_csv is deprecated and will be removed in a future version. Explicitly remove unwanted columns after parsing instead.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'verbose' keyword in pd.read_csv is deprecated and will be removed in a future version.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'keep_date_col' keyword in pd.read_csv is deprecated and will be removed in a future version. Explicitly remove unwanted columns after parsing instead.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n",
      "/Users/stefankrawczyk/dagworks/hamilton/hamilton/plugins/pandas_extensions.py:249: FutureWarning: The 'verbose' keyword in pd.read_csv is deprecated and will be removed in a future version.\n",
      "  df = pd.read_csv(self.path, **self._get_loading_kwargs())\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "            total_signups  total_churn  total_marketing_spend  \\\n",
      "date                                                            \n",
      "2020-01-01           1947          203           52730.560003   \n",
      "2020-01-02           1910          197           49279.312391   \n",
      "2020-01-03           1899          203           51302.996119   \n",
      "2020-01-04           1930          197           56406.767429   \n",
      "2020-01-05           1893          200           62571.780395   \n",
      "...                   ...          ...                    ...   \n",
      "2022-08-28           2827          191          363933.708589   \n",
      "2022-08-29           2843          192          368187.139781   \n",
      "2022-08-30           2822          192          364502.996497   \n",
      "2022-08-31           2870          184          361548.842342   \n",
      "2022-09-01           2853          185          357315.802822   \n",
      "\n",
      "            acquisition_cost  twitter_spend_smoothed  facebook_spend_smoothed  \\\n",
      "date                                                                            \n",
      "2020-01-01         27.082979                0.000000                 0.000000   \n",
      "2020-01-02         25.800687                0.000000                 0.000000   \n",
      "2020-01-03         27.015796                0.000000                 0.000000   \n",
      "2020-01-04         29.226304                0.000000                 0.000000   \n",
      "2020-01-05         33.054295                0.000000                 0.000000   \n",
      "...                      ...                     ...                      ...   \n",
      "2022-08-28        128.734952           119720.253147             96123.914351   \n",
      "2022-08-29        129.506556           120202.788392             95909.302910   \n",
      "2022-08-30        129.164776           120732.077431             96035.431620   \n",
      "2022-08-31        125.975206           121276.011602             96364.649955   \n",
      "2022-09-01        125.242132           121910.888572             96362.987882   \n",
      "\n",
      "            radio_spend_smoothed  tv_spend_smoothed  \\\n",
      "date                                                  \n",
      "2020-01-01              0.000000           0.000000   \n",
      "2020-01-02              0.000000           0.000000   \n",
      "2020-01-03              0.000000           0.000000   \n",
      "2020-01-04              0.000000           0.000000   \n",
      "2020-01-05              0.000000           0.000000   \n",
      "...                          ...                ...   \n",
      "2022-08-28          13640.112643       67931.752455   \n",
      "2022-08-29          13731.030787       67883.385906   \n",
      "2022-08-30          13801.817606       67874.037430   \n",
      "2022-08-31          13815.628266       67796.627318   \n",
      "2022-09-01          13826.582827       67695.406002   \n",
      "\n",
      "            billboards_spend_smoothed  youtube_spend_smoothed  \n",
      "date                                                           \n",
      "2020-01-01                   0.000000                0.000000  \n",
      "2020-01-02                   0.000000                0.000000  \n",
      "2020-01-03                   0.000000                0.000000  \n",
      "2020-01-04                   0.000000                0.000000  \n",
      "2020-01-05                   0.000000                0.000000  \n",
      "...                               ...                     ...  \n",
      "2022-08-28                2370.658271           119720.253147  \n",
      "2022-08-29                2088.525551           120202.788392  \n",
      "2022-08-30                1649.969593           120732.077431  \n",
      "2022-08-31                1337.251853           121276.011602  \n",
      "2022-09-01                 997.866137           121910.888572  \n",
      "\n",
      "[975 rows x 10 columns]\n"
     ]
    },
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"1193pt\" height=\"892pt\"\n",
       " viewBox=\"0.00 0.00 1192.70 891.60\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 887.6)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-887.6 1188.7,-887.6 1188.7,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"31.75,-641.8 31.75,-830.8 139.85,-830.8 139.85,-641.8 31.75,-641.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-813.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- youtube_spend -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>youtube_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M773,-309.6C773,-309.6 675.65,-309.6 675.65,-309.6 669.65,-309.6 663.65,-303.6 663.65,-297.6 663.65,-297.6 663.65,-258 663.65,-258 663.65,-252 669.65,-246 675.65,-246 675.65,-246 773,-246 773,-246 779,-246 785,-252 785,-258 785,-258 785,-297.6 785,-297.6 785,-303.6 779,-309.6 773,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"674.45\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_marketing_spend -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>total_marketing_spend</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M997.6,-309.6C997.6,-309.6 851.5,-309.6 851.5,-309.6 845.5,-309.6 839.5,-303.6 839.5,-297.6 839.5,-297.6 839.5,-258 839.5,-258 839.5,-252 845.5,-246 851.5,-246 851.5,-246 997.6,-246 997.6,-246 1003.6,-246 1009.6,-252 1009.6,-258 1009.6,-258 1009.6,-297.6 1009.6,-297.6 1009.6,-303.6 1003.6,-309.6 997.6,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"850.3\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_marketing_spend</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- youtube_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge19\" class=\"edge\">\n",
       "<title>youtube_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M785.34,-277.8C798.87,-277.8 813.55,-277.8 828.14,-277.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"827.73,-281.3 837.73,-277.8 827.73,-274.3 827.73,-281.3\"/>\n",
       "</g>\n",
       "<!-- total_signups -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>total_signups</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M967.23,-637.6C967.23,-637.6 881.88,-637.6 881.88,-637.6 875.88,-637.6 869.88,-631.6 869.88,-625.6 869.88,-625.6 869.88,-586 869.88,-586 869.88,-580 875.88,-574 881.88,-574 881.88,-574 967.23,-574 967.23,-574 973.23,-574 979.23,-580 979.23,-586 979.23,-586 979.23,-625.6 979.23,-625.6 979.23,-631.6 973.23,-637.6 967.23,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"880.68\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_signups</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- acquisition_cost -->\n",
       "<g id=\"node27\" class=\"node\">\n",
       "<title>acquisition_cost</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1172.7,-473.6C1172.7,-473.6 1068.6,-473.6 1068.6,-473.6 1062.6,-473.6 1056.6,-467.6 1056.6,-461.6 1056.6,-461.6 1056.6,-422 1056.6,-422 1056.6,-416 1062.6,-410 1068.6,-410 1068.6,-410 1172.7,-410 1172.7,-410 1178.7,-410 1184.7,-416 1184.7,-422 1184.7,-422 1184.7,-461.6 1184.7,-461.6 1184.7,-467.6 1178.7,-473.6 1172.7,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"1067.4\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">acquisition_cost</text>\n",
       "<text text-anchor=\"start\" x=\"1101.53\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_signups&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge35\" class=\"edge\">\n",
       "<title>total_signups&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M979.59,-590.36C996.02,-584.08 1013.44,-575.68 1027.6,-564.8 1056.11,-542.9 1080.11,-509.96 1096.45,-483.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1099.36,-485.64 1101.55,-475.27 1093.37,-482.01 1099.36,-485.64\"/>\n",
       "</g>\n",
       "<!-- churn.load_data.data -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>churn.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M164.47,-413.57C164.47,-417.96 129.21,-421.52 85.8,-421.52 42.39,-421.52 7.12,-417.96 7.12,-413.57 7.12,-413.57 7.12,-342.03 7.12,-342.03 7.12,-337.64 42.39,-334.08 85.8,-334.08 129.21,-334.08 164.47,-337.64 164.47,-342.03 164.47,-342.03 164.47,-413.57 164.47,-413.57\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M164.47,-413.57C164.47,-409.19 129.21,-405.62 85.8,-405.62 42.39,-405.62 7.12,-409.19 7.12,-413.57\"/>\n",
       "<text text-anchor=\"start\" x=\"17.92\" y=\"-386.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.92\" y=\"-358.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- churn.select_data.data -->\n",
       "<g id=\"node28\" class=\"node\">\n",
       "<title>churn.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M363.57,-415.6C363.57,-415.6 219.72,-415.6 219.72,-415.6 213.72,-415.6 207.72,-409.6 207.72,-403.6 207.72,-403.6 207.72,-364 207.72,-364 207.72,-358 213.72,-352 219.72,-352 219.72,-352 363.57,-352 363.57,-352 369.57,-352 375.57,-358 375.57,-364 375.57,-364 375.57,-403.6 375.57,-403.6 375.57,-409.6 369.57,-415.6 363.57,-415.6\"/>\n",
       "<text text-anchor=\"start\" x=\"218.52\" y=\"-392.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.52\" y=\"-364.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn.load_data.data&#45;&gt;churn.select_data.data -->\n",
       "<g id=\"edge36\" class=\"edge\">\n",
       "<title>churn.load_data.data&#45;&gt;churn.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M164.74,-380.09C174.97,-380.4 185.55,-380.71 196.03,-381.01\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"195.72,-384.51 205.82,-381.3 195.92,-377.51 195.72,-384.51\"/>\n",
       "</g>\n",
       "<!-- womens_churn -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>womens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M773.38,-883.6C773.38,-883.6 675.28,-883.6 675.28,-883.6 669.28,-883.6 663.28,-877.6 663.28,-871.6 663.28,-871.6 663.28,-832 663.28,-832 663.28,-826 669.28,-820 675.28,-820 675.28,-820 773.38,-820 773.38,-820 779.38,-820 785.38,-826 785.38,-832 785.38,-832 785.38,-871.6 785.38,-871.6 785.38,-877.6 779.38,-883.6 773.38,-883.6\"/>\n",
       "<text text-anchor=\"start\" x=\"674.08\" y=\"-860.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-832.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_churn -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>total_churn</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M960.1,-842.6C960.1,-842.6 889,-842.6 889,-842.6 883,-842.6 877,-836.6 877,-830.6 877,-830.6 877,-791 877,-791 877,-785 883,-779 889,-779 889,-779 960.1,-779 960.1,-779 966.1,-779 972.1,-785 972.1,-791 972.1,-791 972.1,-830.6 972.1,-830.6 972.1,-836.6 966.1,-842.6 960.1,-842.6\"/>\n",
       "<text text-anchor=\"start\" x=\"887.8\" y=\"-819.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_churn</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-791.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>womens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M785.61,-839.33C810.99,-834.08 840.41,-828 865.55,-822.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"866.2,-826.24 875.28,-820.78 864.78,-819.38 866.2,-826.24\"/>\n",
       "</g>\n",
       "<!-- facebook_spend -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>facebook_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M776.38,-555.6C776.38,-555.6 672.28,-555.6 672.28,-555.6 666.28,-555.6 660.28,-549.6 660.28,-543.6 660.28,-543.6 660.28,-504 660.28,-504 660.28,-498 666.28,-492 672.28,-492 672.28,-492 776.38,-492 776.38,-492 782.38,-492 788.38,-498 788.38,-504 788.38,-504 788.38,-543.6 788.38,-543.6 788.38,-549.6 782.38,-555.6 776.38,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"671.08\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M785.13,-491.68C787.85,-488.92 790.34,-485.96 792.5,-482.8 834.23,-421.66 774.85,-376.27 821.5,-318.8 824.19,-315.49 827.18,-312.45 830.4,-309.65\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"832.38,-312.55 838.23,-303.71 828.15,-306.97 832.38,-312.55\"/>\n",
       "</g>\n",
       "<!-- facebook_spend_smoothed -->\n",
       "<g id=\"node26\" class=\"node\">\n",
       "<title>facebook_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1012.98,-555.6C1012.98,-555.6 836.13,-555.6 836.13,-555.6 830.13,-555.6 824.13,-549.6 824.13,-543.6 824.13,-543.6 824.13,-504 824.13,-504 824.13,-498 830.13,-492 836.13,-492 836.13,-492 1012.98,-492 1012.98,-492 1018.98,-492 1024.98,-498 1024.98,-504 1024.98,-504 1024.98,-543.6 1024.98,-543.6 1024.98,-549.6 1018.98,-555.6 1012.98,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"834.93\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;facebook_spend_smoothed -->\n",
       "<g id=\"edge33\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;facebook_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M788.86,-523.8C796.48,-523.8 804.43,-523.8 812.48,-523.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"812.39,-527.3 822.39,-523.8 812.39,-520.3 812.39,-527.3\"/>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-602.6C489.55,-602.6 423.7,-602.6 423.7,-602.6 417.7,-602.6 411.7,-596.6 411.7,-590.6 411.7,-590.6 411.7,-551 411.7,-551 411.7,-545 417.7,-539 423.7,-539 423.7,-539 489.55,-539 489.55,-539 495.55,-539 501.55,-545 501.55,-551 501.55,-551 501.55,-590.6 501.55,-590.6 501.55,-596.6 495.55,-602.6 489.55,-602.6\"/>\n",
       "<text text-anchor=\"start\" x=\"436.75\" y=\"-579.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-551.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- joined_data -->\n",
       "<g id=\"node18\" class=\"node\">\n",
       "<title>joined_data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M615.15,-514.6C615.15,-514.6 542.55,-514.6 542.55,-514.6 536.55,-514.6 530.55,-508.6 530.55,-502.6 530.55,-502.6 530.55,-463 530.55,-463 530.55,-457 536.55,-451 542.55,-451 542.55,-451 615.15,-451 615.15,-451 621.15,-451 627.15,-457 627.15,-463 627.15,-463 627.15,-502.6 627.15,-502.6 627.15,-508.6 621.15,-514.6 615.15,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"541.35\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">joined_data</text>\n",
       "<text text-anchor=\"start\" x=\"544.73\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend&#45;&gt;joined_data -->\n",
       "<g id=\"edge24\" class=\"edge\">\n",
       "<title>spend&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M501.71,-538.53C509.14,-533.09 516.93,-527.39 524.56,-521.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"526.55,-524.69 532.55,-515.96 522.41,-519.04 526.55,-524.69\"/>\n",
       "</g>\n",
       "<!-- womens_signups -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>womens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M780.5,-719.6C780.5,-719.6 668.15,-719.6 668.15,-719.6 662.15,-719.6 656.15,-713.6 656.15,-707.6 656.15,-707.6 656.15,-668 656.15,-668 656.15,-662 662.15,-656 668.15,-656 668.15,-656 780.5,-656 780.5,-656 786.5,-656 792.5,-662 792.5,-668 792.5,-668 792.5,-707.6 792.5,-707.6 792.5,-713.6 786.5,-719.6 780.5,-719.6\"/>\n",
       "<text text-anchor=\"start\" x=\"666.95\" y=\"-696.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-668.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>womens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M792.99,-659.81C814.38,-650.96 837.96,-641.21 859.12,-632.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"860.32,-635.74 868.22,-628.69 857.65,-629.28 860.32,-635.74\"/>\n",
       "</g>\n",
       "<!-- billboards_spend_smoothed -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>billboards_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1015.6,-227.6C1015.6,-227.6 833.5,-227.6 833.5,-227.6 827.5,-227.6 821.5,-221.6 821.5,-215.6 821.5,-215.6 821.5,-176 821.5,-176 821.5,-170 827.5,-164 833.5,-164 833.5,-164 1015.6,-164 1015.6,-164 1021.6,-164 1027.6,-170 1027.6,-176 1027.6,-176 1027.6,-215.6 1027.6,-215.6 1027.6,-221.6 1021.6,-227.6 1015.6,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"832.3\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- spend.select_data.data -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>spend.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M364.7,-607.6C364.7,-607.6 218.6,-607.6 218.6,-607.6 212.6,-607.6 206.6,-601.6 206.6,-595.6 206.6,-595.6 206.6,-556 206.6,-556 206.6,-550 212.6,-544 218.6,-544 218.6,-544 364.7,-544 364.7,-544 370.7,-544 376.7,-550 376.7,-556 376.7,-556 376.7,-595.6 376.7,-595.6 376.7,-601.6 370.7,-607.6 364.7,-607.6\"/>\n",
       "<text text-anchor=\"start\" x=\"217.4\" y=\"-584.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.52\" y=\"-556.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend.select_data.data&#45;&gt;spend -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>spend.select_data.data&#45;&gt;spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M377,-573.21C384.85,-572.97 392.67,-572.73 400.15,-572.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"400.2,-576 410.09,-572.2 399.99,-569.01 400.2,-576\"/>\n",
       "</g>\n",
       "<!-- radio_spend -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>radio_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M763.25,-473.6C763.25,-473.6 685.4,-473.6 685.4,-473.6 679.4,-473.6 673.4,-467.6 673.4,-461.6 673.4,-461.6 673.4,-422 673.4,-422 673.4,-416 679.4,-410 685.4,-410 685.4,-410 763.25,-410 763.25,-410 769.25,-410 775.25,-416 775.25,-422 775.25,-422 775.25,-461.6 775.25,-461.6 775.25,-467.6 769.25,-473.6 763.25,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"684.2\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge20\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M775.44,-416.71C781.76,-412.05 787.68,-406.74 792.5,-400.8 816.85,-370.78 794.75,-346.7 821.5,-318.8 824.23,-315.96 827.17,-313.31 830.29,-310.84\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"832.1,-313.84 838.25,-305.21 828.06,-308.13 832.1,-313.84\"/>\n",
       "</g>\n",
       "<!-- radio_spend_smoothed -->\n",
       "<g id=\"node30\" class=\"node\">\n",
       "<title>radio_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M999.85,-473.6C999.85,-473.6 849.25,-473.6 849.25,-473.6 843.25,-473.6 837.25,-467.6 837.25,-461.6 837.25,-461.6 837.25,-422 837.25,-422 837.25,-416 843.25,-410 849.25,-410 849.25,-410 999.85,-410 999.85,-410 1005.85,-410 1011.85,-416 1011.85,-422 1011.85,-422 1011.85,-461.6 1011.85,-461.6 1011.85,-467.6 1005.85,-473.6 999.85,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"848.05\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;radio_spend_smoothed -->\n",
       "<g id=\"edge37\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;radio_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M775.6,-441.8C790.94,-441.8 808.35,-441.8 825.72,-441.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"825.59,-445.3 835.59,-441.8 825.59,-438.3 825.59,-445.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>tv_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M752.75,-391.6C752.75,-391.6 695.9,-391.6 695.9,-391.6 689.9,-391.6 683.9,-385.6 683.9,-379.6 683.9,-379.6 683.9,-340 683.9,-340 683.9,-334 689.9,-328 695.9,-328 695.9,-328 752.75,-328 752.75,-328 758.75,-328 764.75,-334 764.75,-340 764.75,-340 764.75,-379.6 764.75,-379.6 764.75,-385.6 758.75,-391.6 752.75,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"694.7\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend_smoothed -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>tv_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M989.35,-391.6C989.35,-391.6 859.75,-391.6 859.75,-391.6 853.75,-391.6 847.75,-385.6 847.75,-379.6 847.75,-379.6 847.75,-340 847.75,-340 847.75,-334 853.75,-328 859.75,-328 859.75,-328 989.35,-328 989.35,-328 995.35,-328 1001.35,-334 1001.35,-340 1001.35,-340 1001.35,-379.6 1001.35,-379.6 1001.35,-385.6 995.35,-391.6 989.35,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"858.55\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;tv_spend_smoothed -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;tv_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M764.96,-359.8C785.44,-359.8 811.29,-359.8 836.15,-359.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"835.96,-363.3 845.96,-359.8 835.96,-356.3 835.96,-363.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge18\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M765.02,-342.66C782.33,-335.24 802.88,-326.51 821.5,-318.8 825.05,-317.33 828.67,-315.84 832.33,-314.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"833.38,-317.69 841.31,-310.67 830.73,-311.21 833.38,-317.69\"/>\n",
       "</g>\n",
       "<!-- mens_churn -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>mens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M763.62,-801.6C763.62,-801.6 685.03,-801.6 685.03,-801.6 679.03,-801.6 673.03,-795.6 673.03,-789.6 673.03,-789.6 673.03,-750 673.03,-750 673.03,-744 679.03,-738 685.03,-738 685.03,-738 763.62,-738 763.62,-738 769.62,-738 775.62,-744 775.62,-750 775.62,-750 775.62,-789.6 775.62,-789.6 775.62,-795.6 769.62,-801.6 763.62,-801.6\"/>\n",
       "<text text-anchor=\"start\" x=\"683.83\" y=\"-778.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-750.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- mens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>mens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M776.12,-780.31C803.46,-785.96 837.3,-792.96 865.66,-798.83\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"864.65,-802.19 875.15,-800.79 866.07,-795.34 864.65,-802.19\"/>\n",
       "</g>\n",
       "<!-- total_marketing_spend&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge34\" class=\"edge\">\n",
       "<title>total_marketing_spend&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M1010.04,-307.32C1016.21,-310.79 1022.15,-314.61 1027.6,-318.8 1056.11,-340.7 1080.11,-373.64 1096.45,-399.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"1093.37,-401.59 1101.55,-408.33 1099.36,-397.96 1093.37,-401.59\"/>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node16\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-514.6C489.55,-514.6 423.7,-514.6 423.7,-514.6 417.7,-514.6 411.7,-508.6 411.7,-502.6 411.7,-502.6 411.7,-463 411.7,-463 411.7,-457 417.7,-451 423.7,-451 423.7,-451 489.55,-451 489.55,-451 495.55,-451 501.55,-457 501.55,-463 501.55,-463 501.55,-502.6 501.55,-502.6 501.55,-508.6 495.55,-514.6 489.55,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"430.75\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- signups&#45;&gt;joined_data -->\n",
       "<g id=\"edge25\" class=\"edge\">\n",
       "<title>signups&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M501.71,-482.8C507.35,-482.8 513.18,-482.8 519.01,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"518.61,-486.3 528.61,-482.8 518.61,-479.3 518.61,-486.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend -->\n",
       "<g id=\"node17\" class=\"node\">\n",
       "<title>billboards_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M779,-227.6C779,-227.6 669.65,-227.6 669.65,-227.6 663.65,-227.6 657.65,-221.6 657.65,-215.6 657.65,-215.6 657.65,-176 657.65,-176 657.65,-170 663.65,-164 669.65,-164 669.65,-164 779,-164 779,-164 785,-164 791,-170 791,-176 791,-176 791,-215.6 791,-215.6 791,-221.6 785,-227.6 779,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"668.45\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;billboards_spend_smoothed -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;billboards_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M791.33,-195.8C797.31,-195.8 803.48,-195.8 809.72,-195.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"809.52,-199.3 819.51,-195.8 809.51,-192.3 809.52,-199.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge21\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M791.47,-224.21C801.52,-228.47 811.77,-232.77 821.5,-236.8 825.05,-238.27 828.67,-239.76 832.33,-241.26\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"830.73,-244.39 841.31,-244.93 833.38,-237.91 830.73,-244.39\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;youtube_spend -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;youtube_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M588.63,-450.66C599.65,-415.09 621.42,-357.68 656.15,-318.8 656.41,-318.51 656.66,-318.23 656.93,-317.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"659.21,-320.6 664,-311.15 654.36,-315.55 659.21,-320.6\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_churn -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M579.42,-515.02C580.16,-577.9 589.72,-718.86 656.15,-810.8 656.22,-810.9 656.29,-810.99 656.36,-811.09\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"653.52,-813.16 662.72,-818.4 658.8,-808.56 653.52,-813.16\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;facebook_spend -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;facebook_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M627.63,-496.45C634.5,-498.42 641.71,-500.48 648.95,-502.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"647.9,-505.89 658.47,-505.27 649.82,-499.16 647.9,-505.89\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_signups -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M588.63,-514.94C599.65,-550.51 621.42,-607.92 656.15,-646.8 656.41,-647.09 656.66,-647.37 656.93,-647.66\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"654.36,-650.05 664,-654.45 659.21,-645 654.36,-650.05\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;radio_spend -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;radio_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M627.63,-469.15C638.74,-465.97 650.73,-462.54 662.34,-459.23\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"663.19,-462.62 671.85,-456.51 661.27,-455.89 663.19,-462.62\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;tv_spend -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;tv_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M605.92,-450.85C619.88,-434.81 637.92,-415.68 656.15,-400.8 661.84,-396.16 668.1,-391.65 674.44,-387.44\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"675.93,-390.65 682.46,-382.3 672.15,-384.75 675.93,-390.65\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_churn -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M582.56,-514.83C588.29,-565.21 605.59,-663.89 656.15,-728.8 658.53,-731.86 661.21,-734.74 664.09,-737.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"661.59,-739.92 671.5,-743.66 666.08,-734.55 661.59,-739.92\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;billboards_spend -->\n",
       "<g id=\"edge23\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;billboards_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M582.56,-450.77C588.29,-400.39 605.59,-301.71 656.15,-236.8 656.3,-236.6 656.46,-236.41 656.61,-236.22\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"659,-238.78 663.25,-229.08 653.88,-234.01 659,-238.78\"/>\n",
       "</g>\n",
       "<!-- mens_signups -->\n",
       "<g id=\"node19\" class=\"node\">\n",
       "<title>mens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M770.75,-637.6C770.75,-637.6 677.9,-637.6 677.9,-637.6 671.9,-637.6 665.9,-631.6 665.9,-625.6 665.9,-625.6 665.9,-586 665.9,-586 665.9,-580 671.9,-574 677.9,-574 677.9,-574 770.75,-574 770.75,-574 776.75,-574 782.75,-580 782.75,-586 782.75,-586 782.75,-625.6 782.75,-625.6 782.75,-631.6 776.75,-637.6 770.75,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"676.7\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_signups -->\n",
       "<g id=\"edge27\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M605.92,-514.75C619.88,-530.79 637.92,-549.92 656.15,-564.8 657.08,-565.56 658.02,-566.31 658.97,-567.06\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"656.52,-569.6 666.64,-572.75 660.7,-563.98 656.52,-569.6\"/>\n",
       "</g>\n",
       "<!-- twitter_spend -->\n",
       "<g id=\"node25\" class=\"node\">\n",
       "<title>twitter_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M767.38,-145.6C767.38,-145.6 681.28,-145.6 681.28,-145.6 675.28,-145.6 669.28,-139.6 669.28,-133.6 669.28,-133.6 669.28,-94 669.28,-94 669.28,-88 675.28,-82 681.28,-82 681.28,-82 767.38,-82 767.38,-82 773.38,-82 779.38,-88 779.38,-94 779.38,-94 779.38,-133.6 779.38,-133.6 779.38,-139.6 773.38,-145.6 767.38,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"680.08\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend</text>\n",
       "<text text-anchor=\"start\" x=\"705.2\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;twitter_spend -->\n",
       "<g id=\"edge32\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;twitter_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M579.42,-450.58C580.16,-387.7 589.72,-246.74 656.15,-154.8 657.61,-152.78 659.21,-150.83 660.91,-148.97\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"663.05,-151.76 667.89,-142.33 658.23,-146.69 663.05,-151.76\"/>\n",
       "</g>\n",
       "<!-- mens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>mens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M783.19,-605.8C806.77,-605.8 834.14,-605.8 858.41,-605.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"858.17,-609.3 868.17,-605.8 858.17,-602.3 858.17,-609.3\"/>\n",
       "</g>\n",
       "<!-- twitter_spend_smoothed -->\n",
       "<g id=\"node20\" class=\"node\">\n",
       "<title>twitter_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1003.98,-63.6C1003.98,-63.6 845.13,-63.6 845.13,-63.6 839.13,-63.6 833.13,-57.6 833.13,-51.6 833.13,-51.6 833.13,-12 833.13,-12 833.13,-6 839.13,0 845.13,0 845.13,0 1003.98,0 1003.98,0 1009.98,0 1015.98,-6 1015.98,-12 1015.98,-12 1015.98,-51.6 1015.98,-51.6 1015.98,-57.6 1009.98,-63.6 1003.98,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"843.93\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- spend.load_data.data -->\n",
       "<g id=\"node21\" class=\"node\">\n",
       "<title>spend.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M165.6,-623.57C165.6,-627.96 129.83,-631.52 85.8,-631.52 41.77,-631.52 6,-627.96 6,-623.57 6,-623.57 6,-552.02 6,-552.02 6,-547.64 41.77,-544.07 85.8,-544.07 129.83,-544.07 165.6,-547.64 165.6,-552.02 165.6,-552.02 165.6,-623.57 165.6,-623.57\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M165.6,-623.57C165.6,-619.19 129.83,-615.62 85.8,-615.62 41.77,-615.62 6,-619.19 6,-623.57\"/>\n",
       "<text text-anchor=\"start\" x=\"16.8\" y=\"-596.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.92\" y=\"-568.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- spend.load_data.data&#45;&gt;spend.select_data.data -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>spend.load_data.data&#45;&gt;spend.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M165.91,-583.14C175.4,-582.58 185.17,-582.01 194.86,-581.44\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"194.9,-584.94 204.68,-580.86 194.49,-577.95 194.9,-584.94\"/>\n",
       "</g>\n",
       "<!-- signups.select_data.data -->\n",
       "<g id=\"node22\" class=\"node\">\n",
       "<title>signups.select_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M370.7,-514.6C370.7,-514.6 212.6,-514.6 212.6,-514.6 206.6,-514.6 200.6,-508.6 200.6,-502.6 200.6,-502.6 200.6,-463 200.6,-463 200.6,-457 206.6,-451 212.6,-451 212.6,-451 370.7,-451 370.7,-451 376.7,-451 382.7,-457 382.7,-463 382.7,-463 382.7,-502.6 382.7,-502.6 382.7,-508.6 376.7,-514.6 370.7,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"211.4\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups.select_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"257.52\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- signups.select_data.data&#45;&gt;signups -->\n",
       "<g id=\"edge22\" class=\"edge\">\n",
       "<title>signups.select_data.data&#45;&gt;signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M383.19,-482.8C389.02,-482.8 394.79,-482.8 400.37,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"400.02,-486.3 410.02,-482.8 400.02,-479.3 400.02,-486.3\"/>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node23\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M489.55,-426.6C489.55,-426.6 423.7,-426.6 423.7,-426.6 417.7,-426.6 411.7,-420.6 411.7,-414.6 411.7,-414.6 411.7,-375 411.7,-375 411.7,-369 417.7,-363 423.7,-363 423.7,-363 489.55,-363 489.55,-363 495.55,-363 501.55,-369 501.55,-375 501.55,-375 501.55,-414.6 501.55,-414.6 501.55,-420.6 495.55,-426.6 489.55,-426.6\"/>\n",
       "<text text-anchor=\"start\" x=\"437.88\" y=\"-403.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"422.5\" y=\"-375.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn&#45;&gt;joined_data -->\n",
       "<g id=\"edge26\" class=\"edge\">\n",
       "<title>churn&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M501.71,-427.07C509.14,-432.51 516.93,-438.21 524.56,-443.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"522.41,-446.56 532.55,-449.64 526.55,-440.91 522.41,-446.56\"/>\n",
       "</g>\n",
       "<!-- youtube_spend_smoothed -->\n",
       "<g id=\"node24\" class=\"node\">\n",
       "<title>youtube_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M1009.6,-145.6C1009.6,-145.6 839.5,-145.6 839.5,-145.6 833.5,-145.6 827.5,-139.6 827.5,-133.6 827.5,-133.6 827.5,-94 827.5,-94 827.5,-88 833.5,-82 839.5,-82 839.5,-82 1009.6,-82 1009.6,-82 1015.6,-82 1021.6,-88 1021.6,-94 1021.6,-94 1021.6,-133.6 1021.6,-133.6 1021.6,-139.6 1015.6,-145.6 1009.6,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"838.3\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"905.43\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge17\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M779.77,-142.24C784.45,-146.05 788.8,-150.24 792.5,-154.8 816.85,-184.82 794.75,-208.9 821.5,-236.8 824.23,-239.64 827.17,-242.29 830.29,-244.76\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"828.06,-247.47 838.25,-250.39 832.1,-241.76 828.06,-247.47\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;twitter_spend_smoothed -->\n",
       "<g id=\"edge28\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;twitter_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M779.66,-90.4C793.3,-84.59 807.92,-78.42 821.5,-72.8 825.05,-71.33 828.67,-69.84 832.33,-68.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"833.38,-71.69 841.31,-64.67 830.73,-65.21 833.38,-71.69\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;youtube_spend_smoothed -->\n",
       "<g id=\"edge31\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;youtube_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M779.75,-113.8C791.07,-113.8 803.38,-113.8 815.86,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"815.84,-117.3 825.84,-113.8 815.84,-110.3 815.84,-117.3\"/>\n",
       "</g>\n",
       "<!-- churn.select_data.data&#45;&gt;churn -->\n",
       "<g id=\"edge30\" class=\"edge\">\n",
       "<title>churn.select_data.data&#45;&gt;churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M376.05,-389.43C384.16,-389.98 392.25,-390.52 399.99,-391.04\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"399.7,-394.53 409.92,-391.71 400.18,-387.55 399.7,-394.53\"/>\n",
       "</g>\n",
       "<!-- signups.load_data.data -->\n",
       "<g id=\"node29\" class=\"node\">\n",
       "<title>signups.load_data.data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M171.6,-518.58C171.6,-522.96 133.14,-526.52 85.8,-526.52 38.46,-526.52 0,-522.96 0,-518.58 0,-518.58 0,-447.03 0,-447.03 0,-442.64 38.46,-439.08 85.8,-439.08 133.14,-439.08 171.6,-442.64 171.6,-447.03 171.6,-447.03 171.6,-518.58 171.6,-518.58\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M171.6,-518.58C171.6,-514.19 133.14,-510.63 85.8,-510.63 38.46,-510.63 0,-514.19 0,-518.58\"/>\n",
       "<text text-anchor=\"start\" x=\"10.8\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups.load_data.data</text>\n",
       "<text text-anchor=\"start\" x=\"26.92\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">PandasCSVReader</text>\n",
       "</g>\n",
       "<!-- signups.load_data.data&#45;&gt;signups.select_data.data -->\n",
       "<g id=\"edge29\" class=\"edge\">\n",
       "<title>signups.load_data.data&#45;&gt;signups.select_data.data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M172.07,-482.8C177.58,-482.8 183.15,-482.8 188.72,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"188.63,-486.3 198.63,-482.8 188.63,-479.3 188.63,-486.3\"/>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node31\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M108.22,-686.1C108.22,-686.1 63.37,-686.1 63.37,-686.1 57.37,-686.1 51.37,-680.1 51.37,-674.1 51.37,-674.1 51.37,-661.5 51.37,-661.5 51.37,-655.5 57.37,-649.5 63.37,-649.5 63.37,-649.5 108.22,-649.5 108.22,-649.5 114.22,-649.5 120.22,-655.5 120.22,-661.5 120.22,-661.5 120.22,-674.1 120.22,-674.1 120.22,-680.1 114.22,-686.1 108.22,-686.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-662\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- output -->\n",
       "<g id=\"node32\" class=\"node\">\n",
       "<title>output</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M103.35,-741.1C103.35,-741.1 68.25,-741.1 68.25,-741.1 62.25,-741.1 56.25,-735.1 56.25,-729.1 56.25,-729.1 56.25,-716.5 56.25,-716.5 56.25,-710.5 62.25,-704.5 68.25,-704.5 68.25,-704.5 103.35,-704.5 103.35,-704.5 109.35,-704.5 115.35,-710.5 115.35,-716.5 115.35,-716.5 115.35,-729.1 115.35,-729.1 115.35,-735.1 109.35,-741.1 103.35,-741.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-717\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">output</text>\n",
       "</g>\n",
       "<!-- materializer -->\n",
       "<g id=\"node33\" class=\"node\">\n",
       "<title>materializer</title>\n",
       "<path fill=\"#ffffff\" stroke=\"black\" d=\"M131.85,-796.34C131.85,-798.37 111.21,-800.01 85.8,-800.01 60.39,-800.01 39.75,-798.37 39.75,-796.34 39.75,-796.34 39.75,-763.26 39.75,-763.26 39.75,-761.23 60.39,-759.59 85.8,-759.59 111.21,-759.59 131.85,-761.23 131.85,-763.26 131.85,-763.26 131.85,-796.34 131.85,-796.34\"/>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M131.85,-796.34C131.85,-794.31 111.21,-792.66 85.8,-792.66 60.39,-792.66 39.75,-794.31 39.75,-796.34\"/>\n",
       "<text text-anchor=\"middle\" x=\"85.8\" y=\"-774\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">materializer</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e22ab80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Execution for csv data\n",
    "\n",
    "driver = (hamilton.driver.Builder()\n",
    "          .with_modules(load_data_csv, prep_data)\n",
    "          .with_adapters(base.PandasDataFrameResult())\n",
    "          .build()\n",
    ")\n",
    "print(driver.execute(VARS))\n",
    "\n",
    "csv_execution_graph = driver.visualize_execution(VARS, inputs={\"db_path\": \"./test_data\"})\n",
    "display(csv_execution_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "            total_signups  total_churn  total_marketing_spend  \\\n",
      "date                                                            \n",
      "2022-08-03           2613          213          352562.280870   \n",
      "2022-08-04           2625          216          355564.902400   \n",
      "2022-08-05           2613          212          353811.045380   \n",
      "2022-08-06           2606          214          354899.924090   \n",
      "2022-08-07           2599          209          354891.300149   \n",
      "2022-08-08           2668          212          357514.248166   \n",
      "2022-08-09           2674          214          351627.165746   \n",
      "2022-08-10           2725          217          350941.982457   \n",
      "2022-08-11           2744          212          350736.588485   \n",
      "2022-08-12           2749          206          350944.306317   \n",
      "\n",
      "            acquisition_cost  twitter_spend_smoothed  facebook_spend_smoothed  \\\n",
      "date                                                                            \n",
      "2022-08-03        134.926246                0.000000                 0.000000   \n",
      "2022-08-04        135.453296                0.000000                 0.000000   \n",
      "2022-08-05        135.404151                0.000000                 0.000000   \n",
      "2022-08-06        136.185696                0.000000                 0.000000   \n",
      "2022-08-07        136.549173                0.000000                 0.000000   \n",
      "2022-08-08        134.000843                0.000000                 0.000000   \n",
      "2022-08-09        131.498566           115461.750752            102420.254555   \n",
      "2022-08-10        128.786049           115410.481211            102005.647728   \n",
      "2022-08-11        127.819456           115461.364832            101589.002831   \n",
      "2022-08-12        127.662534           115686.617590            101618.669361   \n",
      "\n",
      "            radio_spend_smoothed  tv_spend_smoothed  \\\n",
      "date                                                  \n",
      "2022-08-03                   0.0                0.0   \n",
      "2022-08-04                   0.0                0.0   \n",
      "2022-08-05                   0.0                0.0   \n",
      "2022-08-06                   0.0                0.0   \n",
      "2022-08-07                   0.0                0.0   \n",
      "2022-08-08                   0.0                0.0   \n",
      "2022-08-09                   0.0                0.0   \n",
      "2022-08-10                   0.0                0.0   \n",
      "2022-08-11                   0.0                0.0   \n",
      "2022-08-12                   0.0                0.0   \n",
      "\n",
      "            billboards_spend_smoothed  youtube_spend_smoothed  \n",
      "date                                                           \n",
      "2022-08-03                   0.000000                0.000000  \n",
      "2022-08-04                   0.000000                0.000000  \n",
      "2022-08-05                   0.000000                0.000000  \n",
      "2022-08-06                   0.000000                0.000000  \n",
      "2022-08-07                   0.000000                0.000000  \n",
      "2022-08-08                   0.000000                0.000000  \n",
      "2022-08-09                1943.742110           115461.750752  \n",
      "2022-08-10                2205.101803           115410.481211  \n",
      "2022-08-11                2394.622409           115461.364832  \n",
      "2022-08-12                2361.296779           115686.617590  \n"
     ]
    },
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 12.0.0 (20240704.0754)\n",
       " -->\n",
       "<!-- Pages: 1 -->\n",
       "<svg width=\"787pt\" height=\"892pt\"\n",
       " viewBox=\"0.00 0.00 786.50 891.60\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 887.6)\">\n",
       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-887.6 782.5,-887.6 782.5,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"8,-606.8 8,-736.8 92.85,-736.8 92.85,-606.8 8,-606.8\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-719.5\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- youtube_spend -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>youtube_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M366.8,-309.6C366.8,-309.6 269.45,-309.6 269.45,-309.6 263.45,-309.6 257.45,-303.6 257.45,-297.6 257.45,-297.6 257.45,-258 257.45,-258 257.45,-252 263.45,-246 269.45,-246 269.45,-246 366.8,-246 366.8,-246 372.8,-246 378.8,-252 378.8,-258 378.8,-258 378.8,-297.6 378.8,-297.6 378.8,-303.6 372.8,-309.6 366.8,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"268.25\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_marketing_spend -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>total_marketing_spend</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M591.4,-309.6C591.4,-309.6 445.3,-309.6 445.3,-309.6 439.3,-309.6 433.3,-303.6 433.3,-297.6 433.3,-297.6 433.3,-258 433.3,-258 433.3,-252 439.3,-246 445.3,-246 445.3,-246 591.4,-246 591.4,-246 597.4,-246 603.4,-252 603.4,-258 603.4,-258 603.4,-297.6 603.4,-297.6 603.4,-303.6 597.4,-309.6 591.4,-309.6\"/>\n",
       "<text text-anchor=\"start\" x=\"444.1\" y=\"-286.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_marketing_spend</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-258.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- youtube_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge17\" class=\"edge\">\n",
       "<title>youtube_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M379.14,-277.8C392.67,-277.8 407.35,-277.8 421.94,-277.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"421.53,-281.3 431.53,-277.8 421.53,-274.3 421.53,-281.3\"/>\n",
       "</g>\n",
       "<!-- total_signups -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>total_signups</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M561.02,-637.6C561.02,-637.6 475.68,-637.6 475.68,-637.6 469.68,-637.6 463.68,-631.6 463.68,-625.6 463.68,-625.6 463.68,-586 463.68,-586 463.68,-580 469.68,-574 475.68,-574 475.68,-574 561.02,-574 561.02,-574 567.02,-574 573.02,-580 573.02,-586 573.02,-586 573.02,-625.6 573.02,-625.6 573.02,-631.6 567.02,-637.6 561.02,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"474.48\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_signups</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- acquisition_cost -->\n",
       "<g id=\"node23\" class=\"node\">\n",
       "<title>acquisition_cost</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M766.5,-473.6C766.5,-473.6 662.4,-473.6 662.4,-473.6 656.4,-473.6 650.4,-467.6 650.4,-461.6 650.4,-461.6 650.4,-422 650.4,-422 650.4,-416 656.4,-410 662.4,-410 662.4,-410 766.5,-410 766.5,-410 772.5,-410 778.5,-416 778.5,-422 778.5,-422 778.5,-461.6 778.5,-461.6 778.5,-467.6 772.5,-473.6 766.5,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"661.2\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">acquisition_cost</text>\n",
       "<text text-anchor=\"start\" x=\"695.33\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_signups&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge30\" class=\"edge\">\n",
       "<title>total_signups&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M573.39,-590.36C589.82,-584.08 607.24,-575.68 621.4,-564.8 649.91,-542.9 673.91,-509.96 690.25,-483.68\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"693.16,-485.64 695.35,-475.27 687.17,-482.01 693.16,-485.64\"/>\n",
       "</g>\n",
       "<!-- womens_churn -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>womens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M367.18,-883.6C367.18,-883.6 269.07,-883.6 269.07,-883.6 263.07,-883.6 257.07,-877.6 257.07,-871.6 257.07,-871.6 257.07,-832 257.07,-832 257.07,-826 263.07,-820 269.07,-820 269.07,-820 367.18,-820 367.18,-820 373.18,-820 379.18,-826 379.18,-832 379.18,-832 379.18,-871.6 379.18,-871.6 379.18,-877.6 373.18,-883.6 367.18,-883.6\"/>\n",
       "<text text-anchor=\"start\" x=\"267.88\" y=\"-860.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-832.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- total_churn -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>total_churn</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M553.9,-842.6C553.9,-842.6 482.8,-842.6 482.8,-842.6 476.8,-842.6 470.8,-836.6 470.8,-830.6 470.8,-830.6 470.8,-791 470.8,-791 470.8,-785 476.8,-779 482.8,-779 482.8,-779 553.9,-779 553.9,-779 559.9,-779 565.9,-785 565.9,-791 565.9,-791 565.9,-830.6 565.9,-830.6 565.9,-836.6 559.9,-842.6 553.9,-842.6\"/>\n",
       "<text text-anchor=\"start\" x=\"481.6\" y=\"-819.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">total_churn</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-791.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>womens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M379.41,-839.33C404.79,-834.08 434.21,-828 459.35,-822.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"460,-826.24 469.08,-820.78 458.58,-819.38 460,-826.24\"/>\n",
       "</g>\n",
       "<!-- facebook_spend -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>facebook_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M370.18,-555.6C370.18,-555.6 266.07,-555.6 266.07,-555.6 260.07,-555.6 254.07,-549.6 254.07,-543.6 254.07,-543.6 254.07,-504 254.07,-504 254.07,-498 260.07,-492 266.07,-492 266.07,-492 370.18,-492 370.18,-492 376.18,-492 382.18,-498 382.18,-504 382.18,-504 382.18,-543.6 382.18,-543.6 382.18,-549.6 376.18,-555.6 370.18,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"264.88\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge14\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M378.93,-491.68C381.65,-488.92 384.14,-485.96 386.3,-482.8 428.03,-421.66 368.65,-376.27 415.3,-318.8 417.99,-315.49 420.98,-312.45 424.2,-309.65\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"426.18,-312.55 432.03,-303.71 421.95,-306.97 426.18,-312.55\"/>\n",
       "</g>\n",
       "<!-- facebook_spend_smoothed -->\n",
       "<g id=\"node22\" class=\"node\">\n",
       "<title>facebook_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M606.77,-555.6C606.77,-555.6 429.93,-555.6 429.93,-555.6 423.93,-555.6 417.93,-549.6 417.93,-543.6 417.93,-543.6 417.93,-504 417.93,-504 417.93,-498 423.93,-492 429.93,-492 429.93,-492 606.77,-492 606.77,-492 612.77,-492 618.77,-498 618.77,-504 618.77,-504 618.77,-543.6 618.77,-543.6 618.77,-549.6 612.77,-555.6 606.77,-555.6\"/>\n",
       "<text text-anchor=\"start\" x=\"428.73\" y=\"-532.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">facebook_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-504.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- facebook_spend&#45;&gt;facebook_spend_smoothed -->\n",
       "<g id=\"edge28\" class=\"edge\">\n",
       "<title>facebook_spend&#45;&gt;facebook_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M382.66,-523.8C390.28,-523.8 398.23,-523.8 406.28,-523.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"406.19,-527.3 416.19,-523.8 406.19,-520.3 406.19,-527.3\"/>\n",
       "</g>\n",
       "<!-- spend -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-596.6C83.35,-596.6 17.5,-596.6 17.5,-596.6 11.5,-596.6 5.5,-590.6 5.5,-584.6 5.5,-584.6 5.5,-545 5.5,-545 5.5,-539 11.5,-533 17.5,-533 17.5,-533 83.35,-533 83.35,-533 89.35,-533 95.35,-539 95.35,-545 95.35,-545 95.35,-584.6 95.35,-584.6 95.35,-590.6 89.35,-596.6 83.35,-596.6\"/>\n",
       "<text text-anchor=\"start\" x=\"30.55\" y=\"-573.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">spend</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-545.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- joined_data -->\n",
       "<g id=\"node16\" class=\"node\">\n",
       "<title>joined_data</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M208.95,-514.6C208.95,-514.6 136.35,-514.6 136.35,-514.6 130.35,-514.6 124.35,-508.6 124.35,-502.6 124.35,-502.6 124.35,-463 124.35,-463 124.35,-457 130.35,-451 136.35,-451 136.35,-451 208.95,-451 208.95,-451 214.95,-451 220.95,-457 220.95,-463 220.95,-463 220.95,-502.6 220.95,-502.6 220.95,-508.6 214.95,-514.6 208.95,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"135.15\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">joined_data</text>\n",
       "<text text-anchor=\"start\" x=\"138.52\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- spend&#45;&gt;joined_data -->\n",
       "<g id=\"edge21\" class=\"edge\">\n",
       "<title>spend&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M95.51,-534.73C101.81,-530.43 108.37,-525.96 114.88,-521.52\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"116.79,-524.45 123.08,-515.93 112.85,-518.67 116.79,-524.45\"/>\n",
       "</g>\n",
       "<!-- womens_signups -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>womens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M374.3,-719.6C374.3,-719.6 261.95,-719.6 261.95,-719.6 255.95,-719.6 249.95,-713.6 249.95,-707.6 249.95,-707.6 249.95,-668 249.95,-668 249.95,-662 255.95,-656 261.95,-656 261.95,-656 374.3,-656 374.3,-656 380.3,-656 386.3,-662 386.3,-668 386.3,-668 386.3,-707.6 386.3,-707.6 386.3,-713.6 380.3,-719.6 374.3,-719.6\"/>\n",
       "<text text-anchor=\"start\" x=\"260.75\" y=\"-696.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">womens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-668.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- womens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>womens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M386.79,-659.81C408.18,-650.96 431.76,-641.21 452.92,-632.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"454.12,-635.74 462.02,-628.69 451.45,-629.28 454.12,-635.74\"/>\n",
       "</g>\n",
       "<!-- billboards_spend_smoothed -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>billboards_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M609.4,-227.6C609.4,-227.6 427.3,-227.6 427.3,-227.6 421.3,-227.6 415.3,-221.6 415.3,-215.6 415.3,-215.6 415.3,-176 415.3,-176 415.3,-170 421.3,-164 427.3,-164 427.3,-164 609.4,-164 609.4,-164 615.4,-164 621.4,-170 621.4,-176 621.4,-176 621.4,-215.6 621.4,-215.6 621.4,-221.6 615.4,-227.6 609.4,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"426.1\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>radio_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M357.05,-473.6C357.05,-473.6 279.2,-473.6 279.2,-473.6 273.2,-473.6 267.2,-467.6 267.2,-461.6 267.2,-461.6 267.2,-422 267.2,-422 267.2,-416 273.2,-410 279.2,-410 279.2,-410 357.05,-410 357.05,-410 363.05,-410 369.05,-416 369.05,-422 369.05,-422 369.05,-461.6 369.05,-461.6 369.05,-467.6 363.05,-473.6 357.05,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"278\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge18\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M369.24,-416.71C375.56,-412.05 381.48,-406.74 386.3,-400.8 410.65,-370.78 388.55,-346.7 415.3,-318.8 418.03,-315.96 420.97,-313.31 424.09,-310.84\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"425.9,-313.84 432.05,-305.21 421.86,-308.13 425.9,-313.84\"/>\n",
       "</g>\n",
       "<!-- radio_spend_smoothed -->\n",
       "<g id=\"node24\" class=\"node\">\n",
       "<title>radio_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M593.65,-473.6C593.65,-473.6 443.05,-473.6 443.05,-473.6 437.05,-473.6 431.05,-467.6 431.05,-461.6 431.05,-461.6 431.05,-422 431.05,-422 431.05,-416 437.05,-410 443.05,-410 443.05,-410 593.65,-410 593.65,-410 599.65,-410 605.65,-416 605.65,-422 605.65,-422 605.65,-461.6 605.65,-461.6 605.65,-467.6 599.65,-473.6 593.65,-473.6\"/>\n",
       "<text text-anchor=\"start\" x=\"441.85\" y=\"-450.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">radio_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-422.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- radio_spend&#45;&gt;radio_spend_smoothed -->\n",
       "<g id=\"edge31\" class=\"edge\">\n",
       "<title>radio_spend&#45;&gt;radio_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M369.4,-441.8C384.74,-441.8 402.15,-441.8 419.52,-441.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"419.39,-445.3 429.39,-441.8 419.39,-438.3 419.39,-445.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>tv_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M346.55,-391.6C346.55,-391.6 289.7,-391.6 289.7,-391.6 283.7,-391.6 277.7,-385.6 277.7,-379.6 277.7,-379.6 277.7,-340 277.7,-340 277.7,-334 283.7,-328 289.7,-328 289.7,-328 346.55,-328 346.55,-328 352.55,-328 358.55,-334 358.55,-340 358.55,-340 358.55,-379.6 358.55,-379.6 358.55,-385.6 352.55,-391.6 346.55,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"288.5\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend_smoothed -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>tv_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M583.15,-391.6C583.15,-391.6 453.55,-391.6 453.55,-391.6 447.55,-391.6 441.55,-385.6 441.55,-379.6 441.55,-379.6 441.55,-340 441.55,-340 441.55,-334 447.55,-328 453.55,-328 453.55,-328 583.15,-328 583.15,-328 589.15,-328 595.15,-334 595.15,-340 595.15,-340 595.15,-379.6 595.15,-379.6 595.15,-385.6 589.15,-391.6 583.15,-391.6\"/>\n",
       "<text text-anchor=\"start\" x=\"452.35\" y=\"-368.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">tv_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-340.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;tv_spend_smoothed -->\n",
       "<g id=\"edge13\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;tv_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M358.76,-359.8C379.24,-359.8 405.09,-359.8 429.95,-359.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"429.76,-363.3 439.76,-359.8 429.76,-356.3 429.76,-363.3\"/>\n",
       "</g>\n",
       "<!-- tv_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge16\" class=\"edge\">\n",
       "<title>tv_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M358.82,-342.66C376.13,-335.24 396.68,-326.51 415.3,-318.8 418.85,-317.33 422.47,-315.84 426.13,-314.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"427.18,-317.69 435.11,-310.67 424.53,-311.21 427.18,-317.69\"/>\n",
       "</g>\n",
       "<!-- mens_churn -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>mens_churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M357.43,-801.6C357.43,-801.6 278.82,-801.6 278.82,-801.6 272.82,-801.6 266.82,-795.6 266.82,-789.6 266.82,-789.6 266.82,-750 266.82,-750 266.82,-744 272.82,-738 278.82,-738 278.82,-738 357.43,-738 357.43,-738 363.43,-738 369.43,-744 369.43,-750 369.43,-750 369.43,-789.6 369.43,-789.6 369.43,-795.6 363.43,-801.6 357.43,-801.6\"/>\n",
       "<text text-anchor=\"start\" x=\"277.62\" y=\"-778.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_churn</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-750.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- mens_churn&#45;&gt;total_churn -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>mens_churn&#45;&gt;total_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M369.92,-780.31C397.26,-785.96 431.1,-792.96 459.46,-798.83\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"458.45,-802.19 468.95,-800.79 459.87,-795.34 458.45,-802.19\"/>\n",
       "</g>\n",
       "<!-- total_marketing_spend&#45;&gt;acquisition_cost -->\n",
       "<g id=\"edge29\" class=\"edge\">\n",
       "<title>total_marketing_spend&#45;&gt;acquisition_cost</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M603.84,-307.32C610.01,-310.79 615.95,-314.61 621.4,-318.8 649.91,-340.7 673.91,-373.64 690.25,-399.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"687.17,-401.59 695.35,-408.33 693.16,-397.96 687.17,-401.59\"/>\n",
       "</g>\n",
       "<!-- signups -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-514.6C83.35,-514.6 17.5,-514.6 17.5,-514.6 11.5,-514.6 5.5,-508.6 5.5,-502.6 5.5,-502.6 5.5,-463 5.5,-463 5.5,-457 11.5,-451 17.5,-451 17.5,-451 83.35,-451 83.35,-451 89.35,-451 95.35,-457 95.35,-463 95.35,-463 95.35,-502.6 95.35,-502.6 95.35,-508.6 89.35,-514.6 83.35,-514.6\"/>\n",
       "<text text-anchor=\"start\" x=\"24.55\" y=\"-491.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">signups</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-463.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- signups&#45;&gt;joined_data -->\n",
       "<g id=\"edge22\" class=\"edge\">\n",
       "<title>signups&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M95.51,-482.8C101.15,-482.8 106.98,-482.8 112.81,-482.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"112.41,-486.3 122.41,-482.8 112.41,-479.3 112.41,-486.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>billboards_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M372.8,-227.6C372.8,-227.6 263.45,-227.6 263.45,-227.6 257.45,-227.6 251.45,-221.6 251.45,-215.6 251.45,-215.6 251.45,-176 251.45,-176 251.45,-170 257.45,-164 263.45,-164 263.45,-164 372.8,-164 372.8,-164 378.8,-164 384.8,-170 384.8,-176 384.8,-176 384.8,-215.6 384.8,-215.6 384.8,-221.6 378.8,-227.6 372.8,-227.6\"/>\n",
       "<text text-anchor=\"start\" x=\"262.25\" y=\"-204.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">billboards_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-176.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;billboards_spend_smoothed -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;billboards_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M385.13,-195.8C391.11,-195.8 397.28,-195.8 403.52,-195.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"403.32,-199.3 413.31,-195.8 403.31,-192.3 403.32,-199.3\"/>\n",
       "</g>\n",
       "<!-- billboards_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge19\" class=\"edge\">\n",
       "<title>billboards_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M385.27,-224.21C395.32,-228.47 405.57,-232.77 415.3,-236.8 418.85,-238.27 422.47,-239.76 426.13,-241.26\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"424.53,-244.39 435.11,-244.93 427.18,-237.91 424.53,-244.39\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;youtube_spend -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;youtube_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M182.43,-450.66C193.45,-415.09 215.22,-357.68 249.95,-318.8 250.21,-318.51 250.46,-318.23 250.73,-317.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"253.01,-320.6 257.8,-311.15 248.16,-315.55 253.01,-320.6\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_churn -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M173.22,-515.02C173.96,-577.9 183.52,-718.86 249.95,-810.8 250.02,-810.9 250.09,-810.99 250.16,-811.09\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"247.32,-813.16 256.52,-818.4 252.6,-808.56 247.32,-813.16\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;facebook_spend -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;facebook_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M221.43,-496.45C228.3,-498.42 235.51,-500.48 242.75,-502.55\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"241.7,-505.89 252.27,-505.27 243.62,-499.16 241.7,-505.89\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;womens_signups -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;womens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M182.43,-514.94C193.45,-550.51 215.22,-607.92 249.95,-646.8 250.21,-647.09 250.46,-647.37 250.73,-647.66\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"248.16,-650.05 257.8,-654.45 253.01,-645 248.16,-650.05\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;radio_spend -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;radio_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M221.43,-469.15C232.54,-465.97 244.53,-462.54 256.14,-459.23\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"256.99,-462.62 265.65,-456.51 255.07,-455.89 256.99,-462.62\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;tv_spend -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;tv_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M199.72,-450.85C213.68,-434.81 231.72,-415.68 249.95,-400.8 255.64,-396.16 261.9,-391.65 268.24,-387.44\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"269.73,-390.65 276.26,-382.3 265.95,-384.75 269.73,-390.65\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_churn -->\n",
       "<g id=\"edge12\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_churn</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M176.36,-514.83C182.09,-565.21 199.39,-663.89 249.95,-728.8 252.33,-731.86 255.01,-734.74 257.89,-737.45\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"255.39,-739.92 265.3,-743.66 259.88,-734.55 255.39,-739.92\"/>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;billboards_spend -->\n",
       "<g id=\"edge20\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;billboards_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M176.36,-450.77C182.09,-400.39 199.39,-301.71 249.95,-236.8 250.1,-236.6 250.26,-236.41 250.41,-236.22\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"252.8,-238.78 257.05,-229.08 247.68,-234.01 252.8,-238.78\"/>\n",
       "</g>\n",
       "<!-- mens_signups -->\n",
       "<g id=\"node17\" class=\"node\">\n",
       "<title>mens_signups</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M364.55,-637.6C364.55,-637.6 271.7,-637.6 271.7,-637.6 265.7,-637.6 259.7,-631.6 259.7,-625.6 259.7,-625.6 259.7,-586 259.7,-586 259.7,-580 265.7,-574 271.7,-574 271.7,-574 364.55,-574 364.55,-574 370.55,-574 376.55,-580 376.55,-586 376.55,-586 376.55,-625.6 376.55,-625.6 376.55,-631.6 370.55,-637.6 364.55,-637.6\"/>\n",
       "<text text-anchor=\"start\" x=\"270.5\" y=\"-614.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">mens_signups</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-586.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;mens_signups -->\n",
       "<g id=\"edge24\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;mens_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M199.72,-514.75C213.68,-530.79 231.72,-549.92 249.95,-564.8 250.88,-565.56 251.82,-566.31 252.77,-567.06\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"250.32,-569.6 260.44,-572.75 254.5,-563.98 250.32,-569.6\"/>\n",
       "</g>\n",
       "<!-- twitter_spend -->\n",
       "<g id=\"node21\" class=\"node\">\n",
       "<title>twitter_spend</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M361.18,-145.6C361.18,-145.6 275.07,-145.6 275.07,-145.6 269.07,-145.6 263.07,-139.6 263.07,-133.6 263.07,-133.6 263.07,-94 263.07,-94 263.07,-88 269.07,-82 275.07,-82 275.07,-82 361.18,-82 361.18,-82 367.18,-82 373.18,-88 373.18,-94 373.18,-94 373.18,-133.6 373.18,-133.6 373.18,-139.6 367.18,-145.6 361.18,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"273.88\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend</text>\n",
       "<text text-anchor=\"start\" x=\"299\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- joined_data&#45;&gt;twitter_spend -->\n",
       "<g id=\"edge27\" class=\"edge\">\n",
       "<title>joined_data&#45;&gt;twitter_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M173.22,-450.58C173.96,-387.7 183.52,-246.74 249.95,-154.8 251.41,-152.78 253.01,-150.83 254.71,-148.97\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"256.85,-151.76 261.69,-142.33 252.03,-146.69 256.85,-151.76\"/>\n",
       "</g>\n",
       "<!-- mens_signups&#45;&gt;total_signups -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>mens_signups&#45;&gt;total_signups</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M376.99,-605.8C400.57,-605.8 427.94,-605.8 452.21,-605.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"451.97,-609.3 461.97,-605.8 451.97,-602.3 451.97,-609.3\"/>\n",
       "</g>\n",
       "<!-- twitter_spend_smoothed -->\n",
       "<g id=\"node18\" class=\"node\">\n",
       "<title>twitter_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M597.77,-63.6C597.77,-63.6 438.93,-63.6 438.93,-63.6 432.93,-63.6 426.93,-57.6 426.93,-51.6 426.93,-51.6 426.93,-12 426.93,-12 426.93,-6 432.93,0 438.93,0 438.93,0 597.77,0 597.77,0 603.77,0 609.77,-6 609.77,-12 609.77,-12 609.77,-51.6 609.77,-51.6 609.77,-57.6 603.77,-63.6 597.77,-63.6\"/>\n",
       "<text text-anchor=\"start\" x=\"437.73\" y=\"-40.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">twitter_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-12.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- churn -->\n",
       "<g id=\"node19\" class=\"node\">\n",
       "<title>churn</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M83.35,-432.6C83.35,-432.6 17.5,-432.6 17.5,-432.6 11.5,-432.6 5.5,-426.6 5.5,-420.6 5.5,-420.6 5.5,-381 5.5,-381 5.5,-375 11.5,-369 17.5,-369 17.5,-369 83.35,-369 83.35,-369 89.35,-369 95.35,-375 95.35,-381 95.35,-381 95.35,-420.6 95.35,-420.6 95.35,-426.6 89.35,-432.6 83.35,-432.6\"/>\n",
       "<text text-anchor=\"start\" x=\"31.67\" y=\"-409.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">churn</text>\n",
       "<text text-anchor=\"start\" x=\"16.3\" y=\"-381.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">DataFrame</text>\n",
       "</g>\n",
       "<!-- churn&#45;&gt;joined_data -->\n",
       "<g id=\"edge23\" class=\"edge\">\n",
       "<title>churn&#45;&gt;joined_data</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M95.51,-430.87C101.81,-435.17 108.37,-439.64 114.88,-444.08\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"112.85,-446.93 123.08,-449.67 116.79,-441.15 112.85,-446.93\"/>\n",
       "</g>\n",
       "<!-- youtube_spend_smoothed -->\n",
       "<g id=\"node20\" class=\"node\">\n",
       "<title>youtube_spend_smoothed</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M603.4,-145.6C603.4,-145.6 433.3,-145.6 433.3,-145.6 427.3,-145.6 421.3,-139.6 421.3,-133.6 421.3,-133.6 421.3,-94 421.3,-94 421.3,-88 427.3,-82 433.3,-82 433.3,-82 603.4,-82 603.4,-82 609.4,-82 615.4,-88 615.4,-94 615.4,-94 615.4,-133.6 615.4,-133.6 615.4,-139.6 609.4,-145.6 603.4,-145.6\"/>\n",
       "<text text-anchor=\"start\" x=\"432.1\" y=\"-122.5\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">youtube_spend_smoothed</text>\n",
       "<text text-anchor=\"start\" x=\"499.23\" y=\"-94.5\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">Series</text>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;total_marketing_spend -->\n",
       "<g id=\"edge15\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;total_marketing_spend</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M373.57,-142.24C378.25,-146.05 382.6,-150.24 386.3,-154.8 410.65,-184.82 388.55,-208.9 415.3,-236.8 418.03,-239.64 420.97,-242.29 424.09,-244.76\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"421.86,-247.47 432.05,-250.39 425.9,-241.76 421.86,-247.47\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;twitter_spend_smoothed -->\n",
       "<g id=\"edge25\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;twitter_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M373.46,-90.4C387.1,-84.59 401.72,-78.42 415.3,-72.8 418.85,-71.33 422.47,-69.84 426.13,-68.34\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"427.18,-71.69 435.11,-64.67 424.53,-65.21 427.18,-71.69\"/>\n",
       "</g>\n",
       "<!-- twitter_spend&#45;&gt;youtube_spend_smoothed -->\n",
       "<g id=\"edge26\" class=\"edge\">\n",
       "<title>twitter_spend&#45;&gt;youtube_spend_smoothed</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M373.55,-113.8C384.87,-113.8 397.18,-113.8 409.66,-113.8\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"409.64,-117.3 419.64,-113.8 409.64,-110.3 409.64,-117.3\"/>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node25\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M72.85,-651.1C72.85,-651.1 28,-651.1 28,-651.1 22,-651.1 16,-645.1 16,-639.1 16,-639.1 16,-626.5 16,-626.5 16,-620.5 22,-614.5 28,-614.5 28,-614.5 72.85,-614.5 72.85,-614.5 78.85,-614.5 84.85,-620.5 84.85,-626.5 84.85,-626.5 84.85,-639.1 84.85,-639.1 84.85,-645.1 78.85,-651.1 72.85,-651.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-627\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "<!-- output -->\n",
       "<g id=\"node26\" class=\"node\">\n",
       "<title>output</title>\n",
       "<path fill=\"#ffc857\" stroke=\"black\" d=\"M67.97,-706.1C67.97,-706.1 32.87,-706.1 32.87,-706.1 26.87,-706.1 20.87,-700.1 20.87,-694.1 20.87,-694.1 20.87,-681.5 20.87,-681.5 20.87,-675.5 26.87,-669.5 32.87,-669.5 32.87,-669.5 67.97,-669.5 67.97,-669.5 73.97,-669.5 79.97,-675.5 79.97,-681.5 79.97,-681.5 79.97,-694.1 79.97,-694.1 79.97,-700.1 73.97,-706.1 67.97,-706.1\"/>\n",
       "<text text-anchor=\"middle\" x=\"50.42\" y=\"-682\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">output</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x14e22aee0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Execution for mock data\n",
    "\n",
    "driver = (hamilton.driver.Builder()\n",
    "          .with_modules(load_data_mock, prep_data)\n",
    "          .with_adapters(base.PandasDataFrameResult())\n",
    "          .build()\n",
    ")\n",
    "print(driver.execute(VARS))\n",
    "\n",
    "mock_execution_graph = driver.visualize_execution(VARS)\n",
    "display(mock_execution_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
